三、MyBatis系列:Mapper 映射 之 关联对象属性及延迟加载

在开发时,经常有这种需求,我拿到了一个order表单实体时,我需要知道该表单是属于哪个用户的。

这时访问 order.getUser() 获取用户信息,这时应该得到一个用户的信息实例。

解决这个问题的方法有三种:

1、通过1条SQL语句进行关联查询,同时读取表单和用户信息;

2、同时发送2条SQL,用于读取 order 与 user信息;

3、先用1条SQL读取order表单信息,访问getUser()时再用另1个SQL读取user信息;

实体定义如下:

 1 public class User {
 2     private Integer id;
 3     private String username;
 4     private Date birthday;
 5     private String sex;
 6     private String address;
 7 }
 8 public class Order {
 9     private int id;
10     private User user;
11     private int number;
12     private Date createtime;
13     private String note;
14 }

第一种方法:使用关联查询的 mapper 的配置

 1 <resultMap type="cn.xleos.mybatis.po.Order" id="orderUserMap">
 2     <id property="id" column="orders_id" />
 3     <result property="createtime" column="orders_createtime" />
 4     <result property="number" column="orders_number" />
 5     <result property="note" column="orders_note" />
 6     <association property="user" javaType="cn.xleos.mybatis.po.User">
 7         <id property="id" column="user_id" />
 8         <result property="username" column="user_username" />
 9         <result property="birthday" column="user_birthday" />
10         <result property="sex" column="user_sex" />
11         <result property="address" column="user_address" />
12     </association>
13 </resultMap>
14 <select id="getOrdersAndUser">
15     SELECT
16     orders.id AS orders_id,
17     orders.number AS orders_number,
18     orders.createtime AS orders_createtime,
19     orders.note AS orders_note,
20     `user`.id AS user_id,
21     `user`.username AS user_username,
22     `user`.birthday AS user_birthday,
23     `user`.sex AS user_sex,
24     `user`.address AS user_address
25     FROM orders
26     INNER JOIN `user` ON `user`.id = orders.user_id
27 </select>

第二种方法,使用二条SQL语句来完成读取表单与用户信息

在读取order关联时 association 节使用了 select="getUserById" 属性,它表示使用 getUserById 这个SQL来读取用户信息。

 1 <resultMap type="cn.xleos.mybatis.po.Order" id="orderMap">
 2     <id property="id" column="id" />
 3     <result property="createtime" column="createtime" />
 4     <result property="number" column="number" />
 5     <result property="note" column="note" />
 6     <association property="user" column="user_id"
 7         javaType="cn.xleos.mybatis.po.User" select="getUserById" />
 8 </resultMap>
 9 <select id="getOrders" resultMap="orderMap">
10     SELECT id, user_id, number, createtime, note, FROM orders
11 </select>
12 <select id="getUserById" parameterMap="int" resultType="cn.xleos.mybatis.po.User">
13     SELECT id, username, birthday, sex, address FROM user where id = #{value}
14 </select>

编写一个单元测试,通过断步来看看MyBatis是如何提交SQL至数据库的。

 1 @Test
 2 public void getOrdersTest() {
 3     SqlSession sqlSession = sqlSessionFactory.openSession();
 4     try {
 5         System.out.println("1. 读取 order 表单数据对象. ");
 6         Order order = sqlSession.selectOne("test.getOrders", 3);
 7         System.out.println("2. 访问表单的 user 属性. ");
 8         User user = order.getUser();
 9         System.out.println(user);
10     } finally {
11         sqlSession.close();
12     }
13 }

以下是日志输出:

 1 DEBUG [main] - Logging initialized using ‘class org.apache.ibatis.logging.log4j.Log4jImpl‘ adapter.
 2 DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
 3 1. 读取 order 表单数据对象.
 4 DEBUG [main] - Opening JDBC Connection
 5 DEBUG [main] - Created connection 2063763486.
 6 DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
 7 DEBUG [main] - ==>  Preparing: SELECT id, user_id, number, createtime, note FROM orders WHERE id = ?
 8 DEBUG [main] - ==> Parameters: 3(Integer)
 9 DEBUG [main] - ====>  Preparing: SELECT id, username, birthday, sex, address FROM user where id = ?
10 DEBUG [main] - ====> Parameters: 1(Integer)
11 DEBUG [main] - <====      Total: 1
12 DEBUG [main] - <==      Total: 1
13 2. 访问表单的 user 属性.
14 User [id=1, username=王五, birthday=Thu Jul 10 00:00:00 CST 2014, sex=2, address=北京市
15 DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
16 DEBUG [main] - Closing JDBC Connection [[email protected]]
17 DEBUG [main] - Returned connection 2063763486 to pool.

通过日志可以发生在读取 order 数据时,就同时发送了2条SQL语句至数据库,读取 order 与 user 数据。

第三种方法,使用延时加载来访问 getUser() 时使用SQL语句读取user信息

1、需要在全局配置文件中添加lazyLoadingEnabled=true;
2、在关联映射(association)中设置 fetchType="lazy" 属性;
3、其它均与第二种方法一致;

1 <resultMap type="cn.xleos.mybatis.po.Order" id="orderMap">
2     <!-- 省略其它属性映射 -->
3     <association property="user" column="user_id"
4         javaType="cn.xleos.mybatis.po.User" select="getUserById" fetchType="lazy" />
5 </resultMap>

也编写一个单元测试,通过断步来看看MyBatis是如何提交SQL至数据库的。

 1 @Test
 2 public void getOrdersLazyTest() {
 3     SqlSession sqlSession = sqlSessionFactory.openSession();
 4     try {
 5         System.out.println("1. 读取 order 表单数据对象. ");
 6         Order order = sqlSession.selectOne("test.getOrders", 3);
 7         System.out.println("2. 访问表单的 user 属性. ");
 8         User user = order.getUser();
 9         System.out.println(user);
10     } finally {
11         sqlSession.close();
12     }
13 }

以下是日志输出:

 1 DEBUG [main] - Logging initialized using ‘class org.apache.ibatis.logging.log4j.Log4jImpl‘ adapter.
 2 DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
 3 1. 读取 order 表单数据对象.
 4 DEBUG [main] - Opening JDBC Connection
 5 DEBUG [main] - Created connection 1071097621.
 6 DEBUG [main] - Setting autocommit to false on JDBC Connection [[email protected]]
 7 DEBUG [main] - ==>  Preparing: SELECT id, user_id, number, createtime, note FROM orders WHERE id = ?
 8 DEBUG [main] - ==> Parameters: 3(Integer)
 9 DEBUG [main] - <==      Total: 1
10 2. 访问表单的 user 属性.
11 DEBUG [main] - ==>  Preparing: SELECT id, username, birthday, sex, address FROM user where id = ?
12 DEBUG [main] - ==> Parameters: 1(Integer)
13 DEBUG [main] - <==      Total: 1
14 User [id=1, username=王五, birthday=Thu Jul 10 00:00:00 CST 2014, sex=2, address=北京市
15 DEBUG [main] - Resetting autocommit to true on JDBC Connection [[email protected]]
16 DEBUG [main] - Closing JDBC Connection [[email protected]]
17 DEBUG [main] - Returned connection 1071097621 to pool.

使用了延时加载后,在读取 order 表单时仅发送一个SQL语句,于数据库查询出 order 对象; 在访问 order.getUser() 时,再发送一条SQL至数据库,读取出 user 记录;

时间: 2024-10-07 07:37:16

三、MyBatis系列:Mapper 映射 之 关联对象属性及延迟加载的相关文章

mybatis的mapper映射配置文件详解

一.标签介绍 insert,update,delete,select,sql,resultMap sql:可被其它语句引用的可重用语句块: resultMap:确定实体类属性与表中字段对应关系: 二.namespace的作用 在MyBatis中,Mapper中的namespace用于绑定Dao接口的,即面向接口编程. 它的好处在于当使用了namespace之后就可以不用写接口实现类,业务逻辑会直接通过这个绑定寻找到相对应的SQL语句进行对应的数据处理 三.parametetType属性 在<in

MyBatis之ResultMap简介,关联对象

MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在.在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值.当提供的返回类型属性是resultType的时候,MyBatis会将Map里面的键值对取出赋给resul

mybatis的mapper映射文件中where,if,foreach等的使用

<?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"> <!-- namespace:命名空间,用于隔离sql,还有一个很重要的作用,后面会讲 --> &

Mybatis——接口与映射文件关联

注册XML: 定义接口方法: public interface BlogMapperI { public List<Blog>getBlogById(List<Integer> ids); public List<Blog>getBlogById2(int[] arrey); public List<Blog>getBlogById3(Map<String,Object> map); public List<Blog> getBlog

6、mybatis学习——mapper映射配置

映射介绍 <!-- 6.mappers:将我们写好的sql映射文件注册到全局配置中 mapper:注册一个sql映射 ①注册配置文件 resource:引用类路径下的sql映射文件 url:引用网络路径或者磁盘路径下的sql映射文件 ②注册映射接口 class:注册单个sql接口: package:批量注册sql接口,属性name指定sql接口所在包 1.有sql映射文件时,映射文件名和接口名必须相同!!!并且在同一目录下!!!: 2.没有sql映射文件:所有的sql都是利用注解写在接口上(不好

mybatis(mapper映射文件)

<!-- parameterType:参数类型,可以省略, 获取自增主键的值: mysql支持自增主键,自增主键值的获取,mybatis也是利用statement.getGenreatedKeys(): useGeneratedKeys="true":使用自增主键获取主键值策略 keyProperty:指定对应的主键属性,也就是mybatis获取到主键值以后,将这个值封装给javaBean的哪个属性 --> <insert id="addEmp"

MyBatis拦截器:给参数对象属性赋值

1 package com.development; 2 3 import java.lang.reflect.InvocationTargetException; 4 import java.util.Date; 5 import java.util.Map; 6 import java.util.Properties; 7 8 import org.apache.commons.beanutils.BeanUtils; 9 import org.apache.ibatis.executor.

Mybatis学习系列(二)Mapper映射文件

Mapper映射文件,作用是用来配置SQL映射语句,根据不同的SQL语句性质,使用不同的标签,mapper文件中常用的标签有<iselect>.<insert>.<update>.<delete> 常见增删改查示例 <!-- namespace:此处使用包名+文件名 的形式 --> <mapper namespace="com.sl.mapper.ProductMapper"> <!--select – 映射

第9章 MyBatis的关系映射

在实际开发中,对数据库的操作通常涉及多张表,涉及了对象和对象之间的关联关系.针对多表之间的操作,MyBatis提供了关联映射,通过关联映射就可以很好的处理对象与对象之间的关联关系 9.1 关联关系概述 一对一:在任意一方引入对方主键作为外键. 一对多:在“多”的一方,添加“一“的一方的主键作为外键.(连着多条线的一方是“多”) 多对多:产生中间关系表,引入两张表的主键作为外键,两个主键成为联合主键或使用新的字段作为主键. 用Java对象描述 class A{ B b; } class B{ A