0


Java-08 深入浅出 MyBatis - 多对多模型 SqlMapConfig 与 Mapper 详细讲解测试

点一下关注吧!!!非常感谢!!持续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

请添加图片描述

目前已经更新到了:

  • MyBatis(正在更新)

多对多

在数据库设计中,“多对多”关系是指两张表中的记录可以互相关联,多条记录可以关联多条记录。例如,“学生”表和“课程”表之间的关系可能是多对多,因为一个学生可以选修多门课程,而一门课程也可能被多名学生选修。

要实现多对多的关系,通常需要使用一个 中间表(关联表)。这个中间表起到桥梁的作用,将两个表的记录通过其主键关联起来。

多对多关系的特点

  • 双向性:A可以关联多个B,同时B也可以关联多个A。
  • 需要中间表:为了表示这种关系,通常使用一个中间表来维护关联。
  • 灵活性高:多对多关系非常适合用来表示复杂的业务逻辑,尤其是在需要动态添加或修改关系时。

多对多关系的扩展

添加额外字段

中间表可以扩展为更多功能。例如,可以为选课添加时间戳、成绩字段、是否通过等。

索引优化

为中间表中的外键添加索引,提高查询性能。

ORM 框架支持

现代框架(如 Hibernate、Django ORM)支持多对多关系的自动管理。在代码中只需要声明模型的关系,底层会自动生成并管理中间表。

查询模型

在这里插入图片描述

用户表和角色的关系,一个用户有多个角色,一个角色被多个用户使用。
多对多的查询的需求,查询用户同时查询出该用户所有的角色。

创建表

wzk_user_role

CREATETABLE`wzk_user_role`(`id`int(11)NOTNULL,`user_id`int(11)NOTNULL,`role_id`int(11)NOTNULL,PRIMARYKEY(`id`)USINGBTREE)ENGINE=InnoDBDEFAULTCHARSET=utf8 COLLATE=utf8_general_ci;

wzk_role

CREATETABLE`wzk_role`(`id`int(11)NOTNULL,`rolename`varchar(255)DEFAULTNULL,PRIMARYKEY(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8 COLLATE=utf8_general_ci;

插入数据

wzk_user_role

INSERTINTO wzk_user_role
VALUES(1,1,1);INSERTINTO wzk_user_role
VALUES(1,2,2);

wzk_role

INSERTINTO wzk_role
VALUES(1,"ADMIN");INSERTINTO wzk_role
VALUES(2,"USER");

查询语句

select u.*,r.*,r.id rid from wzk_user u 
leftjoin wzk_user_role ur on u.id=ur.user_id
innerjoin wzk_role r on ur.role_id=r.id;

执行结果如下所示:
在这里插入图片描述

创建类

WzkUser

这里需要加入新的字段

packageicu.wzk.model;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.util.Date;importjava.util.List;@Data@AllArgsConstructor@NoArgsConstructorpublicclassWzkUser{privateint id;privateString username;privateString password;privateDate birthday;privateList<WzkOrder> orderList;privateList<WzkRole> roleList;}

对应的截图如下所示:
在这里插入图片描述

WzkRole

packageicu.wzk.model;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;@Data@AllArgsConstructor@NoArgsConstructorpublicclassWzkRole{privateInteger id;privateString rolename;}

对应的截图如下所示:
在这里插入图片描述

UserMapper

packageicu.wzk.mapper;importicu.wzk.model.WzkUser;importjava.util.List;publicinterfaceUserMapper{List<WzkUser>findAll();List<WzkUser>findAllUserAndRole();}

对应的截图如下所示:
在这里插入图片描述

UserMapper.xml

<resultMapid="userRoleMap"type="icu.wzk.model.WzkUser"><resultcolumn="id"property="id"></result><resultcolumn="username"property="username"></result><resultcolumn="password"property="password"></result><resultcolumn="birthday"property="birthday"></result><collectionproperty="roleList"ofType="icu.wzk.model.WzkRole"><resultcolumn="rid"property="id"></result><resultcolumn="rolename"property="rolename"></result></collection></resultMap><selectid="findAllUserAndRole"resultMap="userRoleMap">
    SELECT u.*, r.*, r.id rid
    FROM wzk_user u
    LEFT JOIN wzk_user_role ur on u.id=ur.user_id
    INNER JOIN wzk_role r on ur.role_id=r.id;
</select>

对应的截图如下所示:
在这里插入图片描述

编写代码

packageicu.wzk;importicu.wzk.mapper.UserMapper;importicu.wzk.model.WzkUser;importorg.apache.ibatis.io.Resources;importorg.apache.ibatis.session.SqlSession;importorg.apache.ibatis.session.SqlSessionFactory;importorg.apache.ibatis.session.SqlSessionFactoryBuilder;importjava.io.IOException;importjava.io.InputStream;importjava.util.List;publicclassWzkIcu10{publicstaticvoidmain(String[] args)throwsIOException{InputStream resourceAsStream =Resources.getResourceAsStream("sqlMapConfig.xml");SqlSessionFactory sqlSessionFactory =newSqlSessionFactoryBuilder().build(resourceAsStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);List<WzkUser> dataList = userMapper.findAllUserAndRole();
        dataList.forEach(System.out::println);
        sqlSession.close();}}

代码的截图如下所示:
在这里插入图片描述

运行结果

运行上面的代码,控制台输出的结果如下所示:

WzkUser(id=1, username=wzk, password=icu, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=null, roleList=[WzkRole(id=1, rolename=ADMIN)])
WzkUser(id=2, username=wzk2, password=icu2, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=null, roleList=[WzkRole(id=2, rolename=USER)])24/11/12 18:02:33 DEBUG jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@15b204a1]

对应的截图如下所示:
在这里插入图片描述

注意事项

  • 索引优化:为中间表的外键字段创建索引,提升查询性能。
  • 关系约束:使用外键约束维护数据一致性,避免孤立数据。
  • 批量操作:在大规模插入、更新时,尽量使用批量操作,提升效率。
  • 软删除:中间表可以设计“软删除”标志位,用于保留历史记录。

大表的分表与分库

问题背景

在超大规模应用中,单表可能变得过于庞大,导致性能问题。

解决方法

  • 垂直分表:将额外字段分离,减少单表宽度。
  • 水平分表:将记录按学生或课程拆分到多个表。
  • 分库:将不同表分布在多个数据库实例上。

日志和监控

问题背景

多对多关系中的数据修改频繁,容易引入错误,例如重复记录、孤立记录等。

解决方法

  • 日志记录:记录每次数据操作的详细信息。
  • 监控工具:定期检查中间表是否存在孤立记录或重复记录。

暂时小结

优化多对多关系模型需要从多个方面入手:

  • 提升性能:通过索引、分区、批量操作等方式优化查询和更新。
  • 保证数据一致性:通过外键约束和事务处理避免数据异常。
  • 提高灵活性:通过软删除和日志记录保留历史数据,支持恢复和审计。
  • 应对大数据场景:通过分区、分表或分库设计,确保系统扩展性。

本文转载自: https://blog.csdn.net/w776341482/article/details/143988035
版权归原作者 武子康 所有, 如有侵权,请联系我们删除。

“Java-08 深入浅出 MyBatis - 多对多模型 SqlMapConfig 与 Mapper 详细讲解测试”的评论:

还没有评论