1 需求场景
订单表:orders
用户表:users
从查询订单信息出发,关联查询用户信息为一对一查询。如果从用户信息出发,查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
2 one to one
查询所有订单信息,关联查询下单用户信息。
2.1 resultType
2.1.1 分析
1、如果使用resultType进行结果映射,则查询的列名和映射pojo的属性名称要一致。
2、关联查询的结果集,既包含订单信息,又包含用户信息。使用订单po或者用户po类都无法完成结果映射。
3、需要定义扩展po类,此类继承订单信息po类,同时还要包括用户信息:
2.1.2 定义扩展的pojo类
public class OrdersExt extends Orders {
String username;
String email;
}
2.1.3 OrderMapp.xml
<select id="findOrderAndUser" resultType="OrdersExt">
SELECT orders.*,user.username,user.email
FROM orders ,USER
WHERE orders.userid = user.id
</select>
2.1.4 OrderMapper.java
public interface OrdersMapper {
List<OrdersExt> findOrderAndUser();
}
2.1.5 测试
@Test
public void TestFindOrderAndUser(){
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
List<OrdersExt> orders= ordersMapper.findOrderAndUser();
for (OrdersExt oe:orders)
System.out.println(oe);
}
输出
OrdersExt{username='修改', email='test@', id=1, userId=1, num=1}
OrdersExt{username='修改', email='test@', id=2, userId=1, num=1}
2.2 ResultMap
使用resultMap进行结果映射,定义专门的resultMap用于映射一对一查询结果。
2.2.1 OrderExt
public class OrdersExt extends Orders {
// String username;
// String email;
User user;
2.2.2 OrderMapper.xml
<resultMap id="orderAndUserMap" type="OrdersExt">
<!--
id标签:映射查询结果的唯一列(主键列)
column:查询sql的列名
property:映射结果的属性名
-->
<id column="id" property="id"></id>
<result column="userId" property="userId"/>
<result column="num" property="num"/>
<association property="user" javaType="pojo.User">
<id column="userId" property="id"/>
<result column="username" property="username" />
<result column="email" property="email" />
</association>
</resultMap>
<select id="findOrdersAndUserMap" resultMap="orderAndUserMap" >
SELECT O.* ,u.username,u.email
FROM Orders o JOIN USER u ON u.id = o.userId
</select>
association:表示进行一对一关联查询映射
property:表示关联查询的结果存储在orderExt的user属性中
javaType:表示关联查询的映射结果类型
2.2.3 OrderMapper.java
public interface OrdersMapper {
List<OrdersExt> findOrdersAndUserMap();
List<OrdersExt> findOrderAndUser();
}
2.2.4 测试
@Test
public void TestFindOrderAndUserMap(){
SqlSession sqlSession = sqlSessionFactory.openSession();
OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
List<OrdersExt> orders= ordersMapper.findOrdersAndUserMap();
for (OrdersExt oe:orders)
System.out.println(oe);
}
输出
OrdersExt{, user=User{id=1, username='修改', password='null', email='test@', phone='null', address='null'}, id=0, userId=0, num=0}
OrdersExt{, user=User{id=1, username='修改', password='null', email='test@', phone='null', address='null'}, id=0, userId=0, num=0}
3 one to many
根据user查询order信息,一对多查询,只能使用resultMap
3.1 修改User
public class User {
int id;
String username;
String password;
String email;
String phone;
String address;
List<Orders> ordersList;
}
3.2 UserMapper.xml
<resultMap id="userAndOrders" type="user">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="email" column="email" />
<result property="phone" column="phone"/>
<result property="address" column="address"/>
<!-- 一对多关系映射 -->
<collection property="ordersList" ofType="orders">
<id property="id" column="id"/>
<result property="userId" column="id"/>
<result property="num" column="num" />
</collection>
</resultMap>
<select id="getUserAndOrders" resultMap="userAndOrders">
SELECT u.*,o.id,o.num
FROM user u LEFT JOIN orders o ON u.id = o.userId
</select>
Collection标签:定义了一对多关联的结果映射。
property=“ordersList”:关联查询的结果集存储在User对象的上哪个属性。
ofType=“orders”:指定关联查询的结果集中的对象类型即List中的对象类型。
3.3 UserMapper.java
public interface UserMapper {
User findUserById(Integer id);
void addUser(User user);
List<User> getUserByName(String username);
List<User> getUserAndOrders();
}
3.4 测试
@Test
public void testGetUserAndOrders(){
SqlSession sqlSession = null;
try {
sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = userMapper.getUserAndOrders();
for (User u:userList)
System.out.println(u);
}catch (Exception e){
e.printStackTrace();
}finally {
if (sqlSession!=null)
sqlSession.close();
}
}
}
输出
User{id=1, username='修改', password='null', email='test@', phone='121212', address='', ordersList=[pojo.Orders@4eb7f003]}
User{id=9, username='bbb', password='null', email='[email protected]', phone='bbb', address='bbb', ordersList=[pojo.Orders@eafc191]}
User{id=12, username='小小', password='null', email='1@com', phone='123', address='sasas', ordersList=[pojo.Orders@612fc6eb]}
User{id=17, username='小', password='null', email='1@com', phone='123', address='sasas', ordersList=[pojo.Orders@1060b431]}
User{id=20, username='小xiao小', password='null', email='1@com', phone='123', address='sasas', ordersList=[pojo.Orders@612679d6]}
4 延迟加载
延迟加载,也称为懒加载,是指在进行关联查询时,按照设置延迟规则推迟对关联对象的select查询。延迟加载可以有效的减少数据库压力。
Mybatis的延迟加载,需要通过resultMap标签中的association和collection子标签才能演示成功。
注意:MyBatis的延迟加载只是对关联对象的查询有延迟设置,对于主加载对象都是直接执行查询语句的。
4.1 分类
直接加载: 执行完对主加载对象的select语句,马上执行对关联对象的select查询。
侵入式延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。但当要访问主加载对象的详情时,就会马上执行关联对象的select查询。即对关联对象的查询执行,侵入到了主加载对象的详情访问中。也可以这样理解:将关联对象的详情侵入到了主加载对象的详情中,即将关联对象的详情作为主加载对象的详情的一部分出现了。
深度延迟:执行对主加载对象的查询时,不会执行对关联对象的查询。访问主加载对象的详情时也不会执行关联对象的select查询。只有当真正访问关联对象的详情时,才会执行对关联对象的select查询。
4.2 直接加载
lazyLoadingEnabled进行设置,默认就是false。
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="false"/>
</settings>
4.3 侵入式延迟
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 侵入式延迟加载开关 -->
<setting name="aggressiveLazyLoading" value="true"/>
</settings>
4.4 深度延迟加载
<settings>
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 侵入式延迟加载开关 -->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>