在开发时,经常有这种需求,我拿到了一个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