如何在不使用外键的情况下保证关联数据的完整性

发表于:2021-10-20 09:49

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:苏州干饭queen    来源:掘金

分享:
  阿里JAVA规范:【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

  原因:
  当加入外键后,数据库每插入一条或删除一条数据,它都需要去看与之关联的表中是否有这个数据项,例如teacher、student表,teacher管理的student_id是student表的主键,当插入一条teacher数据时,要检查当前插入数据中的student_id是否存在于student表中,保证一致性,删除一条teacher数据时,也会触发一次级联操作,会同步更新和删除student表中的student_id。
  这样就会导致大中型项目的数据库的业务变动,修改数据库的成本变高。外键影响数据库的查询、插入速度,故选择不插入外键,表与表之间的依赖关系要通过应用程序来解决。
  如何做到不使用外键,目前采取的方法:
  例如数据库中有用户表和角色表,以及用户对应的角色关联表。
  用户表UserBean如下:
DROP TABLE "UserBean";
CREATE TABLE "UserBean" (
  "user_id" NUMBER(11) NOT NULL ,
  "username" VARCHAR2(40 BYTE) ,
  "password" VARCHAR2(40 BYTE) 
)

  角色表RoleBean如下:
DROP TABLE "RoleBean";
CREATE TABLE "RoleBean" (
  "role_id" NUMBER(11) NOT NULL ,
  "role_name" VARCHAR2(100 BYTE) ,
  "description" VARCHAR2(200 BYTE) , 
)

  用户角色关联表UserRole如下:
DROP TABLE "UserRole";
CREATE TABLE "UserRole" (
  "user_id" NUMBER(11) NOT NULL ,
  "role_id" NUMBER(11) NOT NULL 
)

  这个时候在数据库表中不添加外键,而是在应用层,写sql语句时关联上。
  后端使用Mybatis连接数据库,当你需要查询某个用户的角色时,在roleMapper中:
public interface RoleMapper {
    //通过username查找用户角色信息
    String findRoleByUsername(@Param("username") String username);
}

  在roleService中:
@Service
public interface RoleService {
    //通过username查找用户角色信息
    String findRoleByUsername(@Param("username") String username);
}

  在roleServiceImpl中:
@Service
public class RoleServiceImpl implements RoleService{

    @Autowired
    RoleMapper roleMapper;
    
    @Override
    public String findRoleByUsername(String username) {
        return roleMapper.findRoleByUsername(username);
    }
}

  而在roleMapper.xml中findRoleByUsername方法的sql语句就可以写为:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.tjm.mapper.RoleMapper">
    <select id="findRoleByUsername" resultType="String" parameterType="String">
        select
               "RoleBean"."role"
        from
             "UserBean"
        RIGHT JOIN "UserRole" on "UserBean"."user_id"="UserRole"."user_id"
        LEFT JOIN "RoleBean" on "RoleBean"."role_id"="UserRole"."role_id"
        where "username"=#{username}
    </select>

</mapper>

  通过right join和left join来关联两张表,查询出我们需要的信息,插入与删除同样这么操作,也就在不使用外键的情况下,保证了数据库中数据的一致性。

  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号