Mybatis 高级映射

1.数据准备

商品订单数据模型:

建表语句

CREATE TABLE `items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL COMMENT '商品名称',
  `price` float(10,1) NOT NULL COMMENT '商品定价',
  `detail` text COMMENT '商品描述',
  `pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
  `createtime` datetime NOT NULL COMMENT '生产日期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/*Table structure for table `orderdetail` */

CREATE TABLE `orderdetail` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orders_id` int(11) NOT NULL COMMENT '订单id',
  `items_id` int(11) NOT NULL COMMENT '商品id',
  `items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',
  PRIMARY KEY (`id`),
  KEY `FK_orderdetail_1` (`orders_id`),
  KEY `FK_orderdetail_2` (`items_id`),
  CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Table structure for table `orders` */

CREATE TABLE `orders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL COMMENT '下单用户id',
  `number` varchar(32) NOT NULL COMMENT '订单号',
  `createtime` datetime NOT NULL COMMENT '创建订单时间',
  `note` varchar(100) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`id`),
  KEY `FK_orders_1` (`user_id`),
  CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*Table structure for table `user` */

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;

````
数据准备:




<div class="se-preview-section-delimiter"></div>

insert into items(id,name,price,detail,pic,createtime) values (1,’台式机’,3000.0,’该电脑质量非常好!!!!’,NULL,’2015-02-03 13:22:53’),(2,’笔记本’,6000.0,’笔记本性能好,质量好!!!!!’,NULL,’2015-02-09 13:22:57’),(3,’背包’,200.0,’名牌背包,容量大质量好!!!!’,NULL,’2015-02-06 13:23:02’);

/Data for the table orderdetail /

insert into orderdetail(id,orders_id,items_id,items_num) values (1,3,1,1),(2,3,2,3),(3,4,3,4),(4,4,2,3);

/Data for the table orders /

insert into orders(id,user_id,number,createtime,note) values (3,1,’1000010’,’2015-02-04 13:22:35’,NULL),(4,1,’1000011’,’2015-02-03 13:22:41’,NULL),(5,10,’1000012’,’2015-02-12 16:13:23’,NULL);

/Data for the table user /

insert into user(id,username,birthday,sex,address) values (1,’王五’,NULL,’2’,NULL),(10,’张三’,’2014-07-10’,’1’,’北京市’),(16,’张小明’,NULL,’1’,’河南郑州’),(22,’陈小明’,NULL,’1’,’河南郑州’),(24,’张三丰’,NULL,’1’,’河南郑州’),(25,’陈小明’,NULL,’1’,’河南郑州’),(26,’王五’,NULL,NULL,NULL);

扫描二维码关注公众号,回复: 1102128 查看本文章





<div class="se-preview-section-delimiter"></div>

### 2.一对一查询




<div class="se-preview-section-delimiter"></div>

#### 2.1 需求
查询订单信息关联查询用户信息




<div class="se-preview-section-delimiter"></div>

#### 2.2 sql语句
查询语句:
先确定主查询表:订单信息表
再确定关联查询表: 用户信息
通过Orders关联查询用户使用user_id 一个外键,只能关联查询出一条用户记录就可以使用内连接




<div class="se-preview-section-delimiter"></div>

SELECT
orders.*,
user.username,
user.sex
FROM
orders,
USER
WHERE orders.user_id = user.id





<div class="se-preview-section-delimiter"></div>

#### 2.3 使用resultType实现




<div class="se-preview-section-delimiter"></div>

##### 2.3.1 创建pojo




<div class="se-preview-section-delimiter"></div>

##### 2.3.2 一对一查询映射的pojo
创建pojo包括订单信息和用户信息,resultType才可以完成映射。
创建OrderCustomer作为自定义pojo,继承sql查询列多的pojo




<div class="se-preview-section-delimiter"></div>

public class OrderCustomer extends Orders{
//补充用户信息
private String username;
private String sex;
private String address;
}
““

2.3.3 mapper.xml

定义mapper.xml

    <!--
            一对一查询使用reusltType完成
        查询订单关联查询用户信息
     -->
     <select id="findOrderUserList" resultType="orderCustom">
             SELECT 
          orders.*,
          user.username,
          user.sex 
        FROM
          orders,
          USER 
        WHERE orders.user_id = user.id 
     </select>   
2.3.4 mapper.java
public interface OrdersMapperCustomer{
  //一对一查询,查询订单关联查询用户
  public List<OrderCustomer> findOrderUserList() throws Exception;
}
2.4 使用resultMap实现一对一
2.4.1 resultMap映射思路

resultMap提供一对一关联查询的映射和一对多关联查询 樱花色,一对一映射思路:将关联查询的信息映射到pojo中,如下:
在orders中创建一个user属性,将关联查询的信息映射到User中

public class Orders{
  private Integer id;
  private Integer userId;
  private String number;
  private Date createTime;
  private String note;
  //关联用户信息
  private User user;
}
2.4.2 mapper.xml

    <!-- 一对一查询使用reusltMap完成
    查询订单关联查询用户信息
     -->
     <select id="findOrderUserListResultMap" resultMap="ordersUserResultMap" >
             SELECT 
          orders.*,
          user.username,
          user.sex 
        FROM
          orders,
          USER 
        WHERE orders.user_id = user.id 
     </select>
2.4.3 resultMap定义
    <!-- 一对一查询resultMap -->

    <resultMap type="orders" id="ordersUserResultMap">
        <!-- 完成了订单信息的映射配置 -->
        <!-- id:订单关联用户查询的唯 一 标识  -->
        <id column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>

        <!-- 下边完成关联信息的映射
        association:用于对关联信息映射到单个pojo
        property:要将关联信息映射到orders的哪个属性中
        javaType:关联信息映射到orders的属性的类型,是user的类型
         -->
        <association property="user" javaType="user">
            <!-- id:关联信息的唯 一标识  -->
            <!-- property: 要映射到user的哪个属性中-->
            <id column="user_id" property="id"/>
            <!-- result就是普通列的映射 -->
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>

        </association>

    </resultMap>
2.4.4 mapper.java
//一对一查询
public List<Orders> findOrderUserListResultMap() throws Exception;
2.5 小结
  • resultType: 要自定义pojo保证sql查询列和pojo的属性对应,这种方法相对简单,所以用用广泛。
  • resultMap: 使用association完成一对一映射需要配置一个resultMap,过程有点复杂,如果要实现延迟加载就只能用resultMap实现,如果为了方便对关联信息进行解析,也可以用association将关联信息映射到pojo中方便解析。

3 一对多查询

3.1 需求

查询所有订单信息及订单写的订单明细信息。

3.2 sql语句

主查询表: 订单表
关联查询表: 订单明细

SELECT 
  orders.*,
  user.username,
  user.sex ,
  orderdetail.id orderdetail_id,
  orderdetail.items_num,
  orderdetail.items_id
FROM
  orders,
  USER,
  orderdetail
WHERE orders.user_id = user.id  AND orders.id = orderdetail.orders_id

3.3 resultMap进行一对多映射思路

resultMap提供collection完成关联信息映射到集合对象。
在orders 类中创建集合属性:

public class orders{
    private Integer id;
   private Integer userId;
   private String number;
   private Date createTime;
   private String note;
   //关联用户信息
   private User user;
   //订单明细
   private List<Orderdetail> orderdetails;
}

3.4 mapper.xml


     <!-- 一对多查询使用reusltMap完成
    查询订单关联查询订单明细
     -->
     <select id="findOrderAndOrderDetails" resultMap="orderAndOrderDetails" >
            SELECT 
      orders.*,
      user.username,
      user.sex ,
      orderdetail.id orderdetail_id,
      orderdetail.items_num,
      orderdetail.items_id
    FROM
      orders,
      USER,
      orderdetail
    WHERE orders.user_id = user.id  AND orders.id = orderdetail.orders_id
     </select>

3.5 resultMap定义

    <!-- 一对多,查询订单及订单明细 -->
    <resultMap type="orders" id="orderAndOrderDetails" extends="ordersUserResultMap">
        <!-- 映射订单信息,和用户信息,这里使用继承ordersUserResultMap -->

        <!-- 映射订单明细信息 
        property:要将关联信息映射到orders的哪个属性中
        ofType:集合中pojo的类型
        -->
        <collection property="orderdetails" ofType="cn.ty.mybatis.po.Orderdetail">
            <!-- id:关联信息订单明细的唯 一标识
                 property:Orderdetail的属性名
              -->
            <id column="orderdetail_id" property="id"/>
            <result column="items_num" property="itemsNum"/>
            <result column="items_id" property="itemsId"/>
        </collection>

    </resultMap>


3.6 mapper.java

//一对多查询,使用resultMap
public List<Orders> findOrderAndOrderDetails() throws Exception;

4.一对多查询(复杂)

4.1 需求

查询所有用户信息,关联查询订单及订单明细及商品信息,订单明细信息中关联查询商品信息

4.2 sql

主查询表:用户信息
关联查询: 订单、订单明细,商品信息

SELECT 
  orders.*,
  user.username,
  user.sex ,
  orderdetail.id orderdetail_id,
  orderdetail.items_num,
  orderdetail.items_id,
  items.name items_name,
  items.detail items_detail
FROM
  orders,
  USER,
  orderdetail,
  items
WHERE orders.user_id = user.id  AND orders.id = orderdetail.orders_id AND items.id = orderdetail.items_id

4.3 pojo定义

在user.java中创建映射的属性:集合 List orderlist
在Orders中创建映射的属性:集合List orderdetails
在Orderdetail中创建商品属性:pojo Items items

public class User implements Serializable {
    private int id;
    private String username;// 用户姓名
    private String sex;// 性别
    private Date birthday;// 生日
    private String address;// 地址

    //多个订单
    private List<Orders> orderlist;
}

public class Orders implements Serializable {
    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    //关联用户信息
    private User user;

    //订单明细
    private List<Orderdetail> orderdetails;
}

public class Orderdetail implements Serializable {
    private Integer id;

    private Integer ordersId;

    private Integer itemsId;

    private Integer itemsNum;

    //商品信息
    private Items items;
}

4.4 mapper.xml


      <!-- 一对多查询使用reusltMap完成
    查询用户及订单和订单明细,关联商品,的信息
     -->
<select id="findUserOrderDetail" resultMap="userOrderDetailResultMap" >
 SELECT 
  orders.*,
  user.username,
  user.sex ,
  orderdetail.id orderdetail_id,
  orderdetail.items_num,
  orderdetail.items_id,
  items.name items_name,
  items.detail items_detail
FROM
  orders,
  USER,
  orderdetail,
  items
WHERE orders.user_id = user.id  AND orders.id = orderdetail.orders_id AND items.id = orderdetail.items_id
</select>

4.5 resultMap


    <!-- 一对多查询,查询用户及订单明细和商品信息 -->
    <resultMap type="user" id="userOrderDetailResultMap">
        <!-- 用户信息映射 -->
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
        <!-- 订单信息 -->
        <collection property="orderlist" ofType="cn.itcast.mybatis.po.Orders">
                <id column="id" property="id"/>
                <result column="user_id" property="userId"/>
                <result column="number" property="number"/>
                <result column="createtime" property="createtime"/>
                <result column="note" property="note"/>
                <!-- 订单明细映射 -->
                <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">
                    <!-- id:关联信息订单明细的唯 一标识
                    property:Orderdetail的属性名
                      -->
                    <id column="orderdetail_id" property="id"/>
                    <result column="items_num" property="itemsNum"/>
                    <result column="items_id" property="itemsId"/>
                    <!-- 商品信息 -->
                    <association property="items" javaType="cn.itcast.mybatis.po.Items">
                        <id column="item_id" property="id"/>
                        <result column="items_name" property="name"/>
                        <result column="items_detail" property="detail"/>
                    </association>
                </collection>
        </collection>



    </resultMap>

4.6 mapper.java

//一对多查询
public List<User> findUserOrderDetail() throws Exception;

5. 延迟加载

5.1 使用延迟加载意义

在进行查询时,为了提高数据库查询性能,尽量使用单表查询,因为单表查询比多表查询速度更快。
如果查询单表就可以满足需求,一开始先查询单表,当需要关联信息时,再关联查询,当需要关联信息再查询这个叫延迟加载。
mybatis中resultMap提供延迟加载功能,通过resultMap配置延迟加载。

5.2 配置mybatis支持延迟加载

设置项 描述 允许值 默认值
lazyLoadingEnabled 全局性设置懒加载。如果设为false,则多有相关联的都会被初始化加载。 true/false false
aggressiveLazyLoading 当设置为true时,懒加载的对象可能被任何属性全部加载否则,每隔属性都按需加载 true/false true
</br>

<!-- 全局配置参数 -->
    <settings>
        <!-- 延迟加载总开关 -->
        <setting name="lazyLoadingEnabled" value="true" />  
        <!-- 设置按需加载 -->
        <setting name="aggressiveLazyLoading" value="false" />
    </settings>

5.3 延迟加载实现

5.3.1 实现思路

需求:
查询订单及用户的信息,一对一查询
刚开始查询订单信息。
当需要用户时调用Orders类中的getUser()方法执行延迟加载,向数据库发出sql

5.3.2 mapper.xml

     <!-- 一对一查询延迟加载
     开始只查询订单,对用户信息进行延迟加载 
      -->
     <select id="findOrderUserListLazyLoading" resultMap="orderCustomLazyLoading">
         SELECT 
          orders.*
        FROM
          orders
     </select>
</mapper>
5.3.3 resultMap
    <!-- 一对一查询延迟加载 的配置 -->
    <resultMap type="orders" id="orderCustomLazyLoading">
        <!-- 完成了订单信息的映射配置 -->
        <!-- id:订单关联用户查询的唯 一 标识 -->
        <id column="id" property="id" />
        <result column="user_id" property="userId" />
        <result column="number" property="number" />
        <result column="createtime" property="createtime" />
        <result column="note" property="note" />
        <!-- 配置用户信息的延迟加载 select:延迟加载执行的sql所在的statement的id,如果不在同一个namespace需要加namespace 
            sql:根据用户id查询用户信息 column:关联查询的列 property:将关联查询的用户信息设置到Orders的哪个属性 -->
        <association property="user"
            select="cn.ty.mybatis.mapper.UserMapper.findUserById" column="user_id"></association>


    </resultMap>
5.3.4 mapper.java
// 一对一查询,延迟加载
public List<Orders> findOrderUserListLazyLoading() throws Exception;
5.2.5 测试代码
    // 一对一查询延迟加载
    @Test
    public void testFindOrderUserListLazyLoading() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 创建mapper代理对象
        OrdersMapperCustom ordersMapperCustom = sqlSession
                .getMapper(OrdersMapperCustom.class);
        // 调用方法
        List<Orders> list = ordersMapperCustom.findOrderUserListLazyLoading();  
        //这里执行延迟加载,要发出sql
        User user = list.get(0).getUser();
        System.out.println(user);

    }
}

6 resultType、resultMap、延迟加载使用场景总结

延迟加载:
延迟加载实现的方法多种多样,在只查询单表就可以满足需求,为了提高数据库查询性能使用延迟加载,再查询关联信息。
mybatis提供延迟加载的功能用于service层。

resultType:
作用:
将查询结果按照sql列名pojo属性名一致性映射到pojo中
场合:
常见一些明细记录的展示,将关联查询信息全部展示在页面中,此时可直接使用resultType 将每一条记录映射到pojo中,在前端遍历list即可。
resultMap:
使用association 和 collection 完成一对一和一对多高级映射。
association:
作用:
将关联查询信息映射到一个pojo类
场合:
为了方便获取关联信息可以使用association将关联订单映射为pojo,比如查询订单及关联用户信息。

collection:
作用:
将关联查询信息映射到一个list集合中。
场合:
为了方便获取关联信息可以使用collection将关联信息映射到list集合中,比如:查询用户权限范围模块和功能,可使用collection将模块和功能列表映射到list中。

猜你喜欢

转载自blog.csdn.net/fd2025/article/details/80467855