当前位置:   article > 正文

MyBatis3.x整理:(四)对象关系映射_mybatis--对象关系映射细节详解

mybatis--对象关系映射细节详解

一.多对一

案例:多个员工对象同属于同个部门对象

模型对象设计

 

表设计:

1.保存操作

DepartmentMapper.xml

  1. <!-- 添加 -->
  2. <insert id="save" useGeneratedKeys="true" keyProperty="id" >
  3. insert into department (name) values (#{name})
  4. </insert>

EmployeeMapper.xml

  1. <!-- 添加 -->
  2. <insert id="save" useGeneratedKeys="true" keyProperty="id" >
  3. insert into employee_new (name,dept_id) values (#{name},#{dept.id})
  4. </insert>

 测试代码

  1. Department department = new Department();
  2. department.setName("开发部");
  3. Employee user1 = new Employee();
  4. user1.setName("王小子2");
  5. user1.setDept(department);//维护对象关系
  6. Employee user2 = new Employee();
  7. user2.setName("兰兰");
  8. user2.setDept(department);//维护对象关系
  9. SqlSession session = MybatisUtil.getSession();
  10. DepartmentMapper departmentMapper = session.getMapper(DepartmentMapper.class);
  11. EmployeeMapper userMapper = session.getMapper(EmployeeMapper.class);
  12. departmentMapper.save(department);
  13. userMapper.save(user1);
  14. userMapper.save(user2);
  15. //提交事务
  16. session.commit();
  17. session.close();
  18. System.out.println(department);
  19. System.out.println(user1);
  20. System.out.println(user2);

 

2.内联映射

association元素:

     property属性:关联对象属性名

     javaType属性:关联对象属性类型

多表连接查询的SQL:

<select id="get" resultMap="BaseResultMap" >
        select e.id,e.name,d.id as d_id,d.name as d_name from  employee_new e join department d on e.dept_id = d.id where e.id = #{id}
    </select> 

方式一,使用级联方式来封装对象(不用)。

  1. <resultMap id="BaseResultMap" type="Employee" >
  2. <id column="id" property="id"/>
  3. <result column="name" property="name"/>
  4. <result column="d_id" property="dept.id"/>
  5. <result column="d_name" property="dept.name"/>
  6. </resultMap>

 方式二,使用association元素(常用)

  1. <resultMap id="BaseResultMap" type="Employee" >
  2. <id column="id" property="id"/>
  3. <result column="name" property="name"/>
  4. <!-- 处理关联对象 -->
  5. <!-- 方法一:额外SQL语句 -->
  6. <!-- 方法二:内联关系
  7. <result column="d_id" property="dept.id"/>
  8. <result column="d_name" property="dept.name"/>
  9. -->
  10. <!-- 方法三
  11. 可以给association添加属性columnPrefix="d_",下边字段可以统一少写"d_"
  12. -->
  13. <association property="dept" javaType="Department" >
  14. <id column="d_id" property="id"/>
  15. <result column="d_name" property="name"/>
  16. </association>
  17. </resultMap>

 

 

3.额外SQL

association元素:

     select属性:发送的额外SQL语句

     column属性:将指定列的值传递给额外SQL

  1. <resultMap id="BaseResultMap" type="Employee" >
  2. <id column="id" property="id"/>
  3. <result column="name" property="name"/>
  4. <association property="dept"
  5. select="com.bigfong.mybatis.many2one.mapper.EmployeeMapper.get"
  6. column="dept_id">
  7. </association>
  8. </resultMap>

 使用额外SQL语句,在查询多对一下,会产生N+1问题

 

内联映射和额外SQL的选择

 在开发中,多对一的关系,一般的都是在列表中显示,通常直播使用多表查询,也就是内联查询处理

如果在当前页面不显示数据,需要进入另一个页面才显示的数据,此时选用额外SQL方式

 

 

二.一对多 

模型对象设计:

表设计(外键在many方) 

 

1.额外SQL

DepartmentMapper.xml

  1. <resultMap type="Department" id="BaseResultMap">
  2. <id column="id" property="id"/>
  3. <result column="name" property="name"/>
  4. <!-- 针对单一对象的属性,使用association -->
  5. <!-- 针对集合类型的属性,使用collection,这里:List<Employee> emps -->
  6. <!--
  7. ofType:表示集合中泛型的类型
  8. -->
  9. <collection property="emps"
  10. ofType="Employee"
  11. select="com.bigfong.mybatis.one2many.mapper.EmployeeMapper.selectByDeptId"
  12. column="id"
  13. />
  14. </resultMap>
  15. <select id="get" resultMap="BaseResultMap">
  16. SELECT id,name FROM department WHERE id = #{id}
  17. </select>

EmployeeMapper.xml

  1. <select id="selectByDeptId" resultType="Employee">
  2. select id,name,dept_id as deptId from employee_new where dept_id = #{deptId}
  3. </select>

 

 

2.内联映射

使用一条语句查询出部门和该部门对应的咒工(一般不用)

  1. <resultMap type="Department" id="BaseResultMap2">
  2. <id column="id" property="id"/>
  3. <result column="name" property="name"/>
  4. <!-- 针对单一对象的属性,使用association -->
  5. <!-- 针对集合类型的属性,使用collection,这里:List<Employee> emps
  6. <collection property="emps"
  7. ofType="Employee"
  8. select="com.bigfong.mybatis.one2many.mapper.EmployeeMapper.selectByDeptId"
  9. column="id"
  10. />-->
  11. <collection property="emps" ofType="Employee">
  12. <id column="e_id" property="id"/>
  13. <result column="e_name" property="name"/>
  14. <result column="id" property="deptId"/>
  15. </collection>
  16. </resultMap>

内联映射和额外SQL的选择:

 内联映射:使用多表查询,一次性查询出所有数据,在列表中一起显示的数据

额外SQL: 分步查询出所有数据,在另一个页面单独显示的数据

 

三.延迟加载 

 配置细节:

1.Mybatis缺省情况下,禁用了延迟加载

2.Mybatis会很积极地去查询关联对象

3.Mybatis中缺省情况下,调用equals,clone,hashCode,toString都会触发延迟加载,一般我们保留clone就可以了,也就是说调用many方对象的toString,hashCode,equals方法依然不会去发送查询one方的SQL

 

mybatis-config.xml中的配置

  1. <settings>
  2. <!-- 开启延迟加载 对于关联对象查询为: 额外SQL的配置方式 有效 -->
  3. <setting name="lazyLoadingEnabled" value="true"/>
  4. <!-- 设置不要积极的去查询关联对象 -->
  5. <setting name="aggressiveLazyLoading" value="false"/>
  6. <!-- 延迟加载的触发的方法 -->
  7. <setting name="lazyLoadTriggerMethods" value="clone"/>
  8. </settings>

 

四.关联对象配置选择

在开发中, 

1)针对单属性对象,使用association元素,通常直接 使用多表查询操作,即使用内联处理

 2)针对集合属性对象,使用collection元素,通常使用延迟加载,即额外SQL查询处理

 

 五.多对多

一个A对象属于多个B对象,一个B对象属性多个A对象(单向关系) 

模型对象设计

表设计:

 中间表的主键设计:

方式一.中间表不设置主键

方式二.把student_id和teach_id列设计为联合主键

 

1.保存操作 

因为存在中间表的缘故,所以必须发送额外的SQL去维护中间表的关系

StudentMapper.xml:

  1. <insert id="insertRelationWithTeacher">
  2. insert into student_teacher (student_id,teacher_id) values (#{studentId},#{teacherId})
  3. </insert>

 测试代码:

  1. Teacher t1 = new Teacher();
  2. t1.setName("老师1");
  3. Teacher t2 = new Teacher();
  4. t2.setName("老师2");
  5. Student s1 = new Student();
  6. s1.setName("小七");
  7. Student s2 = new Student();
  8. s2.setName("花花");
  9. //维护对象之间关系
  10. s1.getTeachers().add(t1);
  11. s1.getTeachers().add(t2);
  12. s2.getTeachers().add(t1);
  13. s2.getTeachers().add(t2);
  14. SqlSession session = MybatisUtil.getSession();
  15. TeacherMapper teacherMapper = session.getMapper(TeacherMapper.class);
  16. StudentMapper studentMapper = session.getMapper(StudentMapper.class);
  17. teacherMapper.save(t1);
  18. teacherMapper.save(t2);
  19. studentMapper.save(s1);
  20. studentMapper.save(s2);
  21. //维护学生和老师关系的中间表的数据
  22. for(Teacher t:s1.getTeachers()) {
  23. studentMapper.insertRelationWithTeacher(s1.getId(), t.getId());
  24. }
  25. for(Teacher t:s2.getTeachers()) {
  26. studentMapper.insertRelationWithTeacher(s2.getId(), t.getId());
  27. }
  28. //提交事务
  29. session.commit();
  30. session.close();

 

2.查询操作

因为此时teahcers属性是集合类型,所以使用额外SQL是合理的,使用内联查询时不合理

StudentMapper.xml:

  1. <resultMap type="Student" id="BaseResultMap">
  2. <id column="id" property="id"/>
  3. <result column="name" property="name"/>
  4. <collection property="teachers" ofType="Teacher"
  5. select="com.bigfong.mybatis.many2many.mapper.TeacherMapper.selectByStudentId"
  6. column="id"
  7. />
  8. </resultMap>
  9. <select id="get" resultMap="BaseResultMap">
  10. select id,name from student where id = #{id}
  11. </select>

 TeacherMapper.xml:

  1. <select id="selectByStudentId" resultType="Teacher">
  2. select t.id,t.name from teacher t join student_teacher st on t.id=st.teacher_id where st.student_id = #{id}
  3. </select>

 

3.删除操作之前,必须先删除中间表中关联的数据

StudentMapper.xml

  1. <delete id="delete">
  2. delete from student where id =#{id}
  3. </delete>
  4. <delete id="deleteRelationWithTeacher">
  5. delete from student_teacher where student_id =#{studentId}
  6. </delete>

 

 

源码下载

上一篇: MyBatis3.x整理:(三)动态SQL

下一篇: MyBatis3.x整理:(五)缓存机制​​​​​​​

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/625634
推荐阅读
相关标签
  

闽ICP备14008679号