Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多

时间:2024-12-04 18:14:50


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

大数据篇正在更新!

  • MyBatis(正在更新)

一对多

查询模型

用户表和订单表的关系为,一个用户有多个订单,一个订单只属于一个用户,一对多查询的需求:查询一个用户,与此同时查询出该用户具有的订单。

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_springboot

一对多优点

数据清晰,关系明确。
数据完整性可以通过外键约束强制维护。
查询灵活,通过关联表可以获取丰富的数据。

一对多缺点

对于复杂查询,可能涉及多次连接(JOIN),性能稍差。
数据模型耦合较紧,当表结构发生变更时,影响范围较大。

编写代码

UserMapper

修改 UserMapper,加入新的方法findAllUserAndOderWithAnnotation,通过注解的方式实现:

@Select("select * from wzk_user")
@Results({
        @Result(id = true, property = "id", column = "id"),
        @Result(property = "username", column = "username"),
        @Result(property = "password", column = "password"),
        @Result(property = "birthday", column = "birthday"),
        @Result(property = "roleList", column = "id", javaType = List.class,
                many = @Many(select = "icu.wzk.mapper.OrderMapper.findByUserIdWithAnnotation"))
})
List<WzkUser> findAllUserAndOderWithAnnotation();

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_开发语言_02

OrderMapper

修改 OrderMapper,加入了 findByUserIdWithAnnotation,因为在 UserMapper 中,刚才的方法需要调用。

@Select("select * from wzk_orders where id = #{id}")
List<WzkOrder> findByUserIdWithAnnotation(int id);

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_mysql_03

调用代码

public class WzkIcu12 {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<WzkUser> dataList = userMapper.findAllUserAndOderWithAnnotation();
        dataList.forEach(System.out::println);
        sqlSession.close();
    }
}

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_开发语言_04

测试结果

控制台输出的结果如下所示:

WzkUser(id=1, username=wzk, password=icu, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=null, roleList=[WzkOrder(id=1, ordertime=Mon Nov 11 00:00:00 CST 2024, total=100.0, user=null)])
WzkUser(id=2, username=wzk2, password=icu2, birthday=Mon Nov 11 00:00:00 CST 2024, orderList=null, roleList=[WzkOrder(id=2, ordertime=Mon Nov 11 00:00:00 CST 2024, total=200.0, user=null)])
24/11/13 09:34:12 DEBUG jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@75329a49]

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_开发语言_05

多对多

查询模型

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

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_mysql_06

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

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

多对多关系的特点

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

多对多关系的扩展

添加额外字段

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

索引优化

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

ORM 框架支持

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

编写代码

UserMapper

修改 UserMapper,加入新的方法findAllUserAndRoleWithAnnotation,使用注解来实现:

@Select("select * from wzk_user")
@Results({
        @Result(id = true,property = "id",column = "id"),
        @Result(property = "username",column = "username"),
        @Result(property = "password",column = "password"),
        @Result(property = "birthday",column = "birthday"),
        @Result(property = "roleList",column = "id",
                javaType = List.class,
                many = @Many(select = "icu.wzk.mapper.RoleMapper.findByUserIdWithAnnotation"))
})
List<WzkUser> findAllUserAndRoleWithAnnotation();

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_mybatis_07

RoleMapper

新建了 RoleMapper:

public interface RoleMapper {

    @Select("select * from wzk_role r, wzk_user_role ur where r.id=ur.role_id and ur.user_id=#{uid}")
    List<WzkRole> findByUserIdWithAnnotation(int uid);

}

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_mysql_08

调用代码

public class WzkIcu13 {
    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<WzkUser> dataList = userMapper.findAllUserAndRoleWithAnnotation();
        dataList.forEach(System.out::println);
        sqlSession.close();
    }
}

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_开发语言_09

测试结果

对上述的代码进行执行,控制台输出的结果如下所示:

24/11/13 10:01:13 DEBUG UserMapper.findAllUserAndRoleWithAnnotation: <==      Total: 2
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/13 10:01:13 DEBUG jdbc.JdbcTransaction: Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@1e802ef9]

对应的截图如下所示:

Java-10 深入浅出 MyBatis - 注解开发 注解映射 一对多 与 多对多_mysql_10

注解模式的优缺点

优点

  • 开发简单:无需复杂的 XML 配置文件。
  • 代码集中:SQL 语句和逻辑写在一起,便于维护。
  • 便捷性:适合简单的 CRUD 操作,代码量少。

缺点

  • 可读性差:SQL 语句嵌入代码,可能不易阅读。
  • 复杂 SQL 不易维护:对于复杂 SQL,注解模式不如 XML 清晰。
  • 可扩展性有限:不易支持动态 SQL 和高级功能。