程序员人生 网站导航

Mybatis学习笔记(三)—高级映射,延迟加载

栏目:框架设计时间:2016-07-28 09:10:19

本文主要介绍了如何使用resultMap完成高级映照;分析数据库中表之间的关系(1对1、1对多、多对多)

如何在mapper.xml文件中配置resultMap实现1对1、1对多、多对多;mybatis如何实现延迟加载

1       数据模型

数据库中有已导入的4个表:items:(商品信息表);orderdetail:(定单明细表);orders:(定单表);user:(用户表)

1 CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname VARCHAR(32) NOT NULL COMMENT '商品名称', 4 price FLOAT(10,1) NOT NULL COMMENT '商品定价', 5 detail TEXT COMMENT '商品描写', 6 pic VARCHAR(64) DEFAULT NULL COMMENT '商品图片', 7 createtime DATETIME NOT NULL COMMENT '生产日期', 8 PRIMARY KEY (id) 9 ) DEFAULT CHARSET=utf8; 10 11 /*Table structure for table `orderdetail` */ 12 13 CREATE TABLE orderdetail ( 14 id INT NOT NULL AUTO_INCREMENT, 15 orders_id INT NOT NULL COMMENT '定单id', 16 items_id INT NOT NULL COMMENT '商品id', 17 items_num INT DEFAULT NULL COMMENT '商品购买数量', 18 PRIMARY KEY (id), 19 KEY `FK_orderdetail_1` (`orders_id`), 20 KEY `FK_orderdetail_2` (`items_id`), 21 CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 22 CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 23 ) DEFAULT CHARSET=utf8; 24 25 /*Table structure for table `orders` */ 26 27 CREATE TABLE orders ( 28 id INT NOT NULL AUTO_INCREMENT, 29 user_id INT NOT NULL COMMENT '下单用户id', 30 number VARCHAR(30) NOT NULL COMMENT '定单号', 31 createtime DATETIME NOT NULL COMMENT '创建定单时间', 32 note VARCHAR(100) DEFAULT NULL COMMENT '备注', 33 PRIMARY KEY (`id`), 34 KEY `FK_orders_1` (`user_id`), 35 CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 36 ) DEFAULT CHARSET=utf8; 37 38 /*Table structure for table `t_user` */ 39 40 CREATE TABLE user ( 41 id INT NOT NULL AUTO_INCREMENT, 42 username VARCHAR(32) NOT NULL COMMENT '用户名称', 43 birthday DATE DEFAULT NULL COMMENT '生日', 44 sex CHAR(1) DEFAULT NULL COMMENT '性别', 45 address VARCHAR(256) DEFAULT NULL COMMENT '地址', 46 PRIMARY KEY (`id`) 47 ) DEFAULT CHARSET=utf8;

测试数据代码:

1 /*Data for the table `items` */ 2 3 INSERT INTO items(itemsname,price,detail,pic,createtime) VALUES 4 ('台式机',3000.0,'该电脑质量非常好!',NULL,'2015-07-07 13:28:53'), 5 ('笔记本',6000.0,'笔记本性能好,质量好!',NULL,'2015-07-08 13:22:57'), 6 ('背包',200.0,'名牌背包,容量大质量好!',NULL,'2015-07-010 13:25:02'); 7 8 /*Data for the table `orderdetail` */ 9 10 INSERT INTO `orderdetail`(`orders_id`,`items_id`,`items_num`) VALUES 11 (1,1,1), 12 (1,2,3), 13 (2,3,4), 14 (3,2,3); 15 16 /*Data for the table `orders` */ 17 18 INSERT INTO `orders`(`user_id`,`number`,`createtime`,`note`) VALUES 19 (1,'1000010','2015-06-04 13:22:35',NULL), 20 (1,'1000011','2015-07-08 13:22:41',NULL), 21 (2,'1000012','2015-07⑴7 14:13:23',NULL), 22 (3,'1000012','2015-07⑴6 18:13:23',NULL), 23 (4,'1000012','2015-07⑴5 19:13:23',NULL), 24 (5,'1000012','2015-07⑴4 17:13:23',NULL), 25 (6,'1000012','2015-07⑴3 16:13:23',NULL); 26 27 /*Data for the table `user` */ 28 29 INSERT INTO `user`(`username`,`birthday`,`sex`,`address`) VALUES 30 ('王5',NULL,'2',NULL), 31 ('张3','2014-07⑴0','1','北京市'), 32 ('张小明',NULL,'1','河南郑州'), 33 ('陈小明',NULL,'1','河南郑州'), 34 ('张3丰',NULL,'1','河南郑州'), 35 ('陈小明',NULL,'1','河南郑州'), 36 ('王5',NULL,NULL,NULL), 37 ('小A','2015-06⑵7','2','北京'), 38 ('小B','2015-06⑵7','2','北京'), 39 ('小C','2015-06⑵7','1','北京'), 40 ('小D','2015-06⑵7','2','北京');

用户表user:

记录了购买商品的用户

 

定单表orders:

记录了用户所创建的定单信息

 

定单明细表orderdetail:

记录了用户创建定单的详细信息

 

商品信息表items:

记录了商家提供的商品信息

 

分析表与表之间的关系:

 

用户user和定单orders:

 

user---->orders:1个用户可以创建多个定单   1对多

orders-->user:1个定单只能由1个用户创建  1对1

 

定单orders和定单明细orderdetail:

orders-->orderdetail:1个定单可以包括多个定单明细  1对多

orderdetail-->orders:1个定单明细只属于1个定单  1对1

 

定单明细orderdetail和商品信息items:

 

orderdetail-->items:1个定单明细对应1个商品信息1对1

items--> orderdetail:1个商品对应多个定单明细  1对多

以下是这4个表的对应关系:


1.1     项目的目录结构

 

2       1对1查询

2.1     需求

使用Mapper接口代理的方式查询定单信息关联查询用户信息

2.2     sql语句

查询语句:

先肯定主查询表:定单信息表

再肯定关联查询表:用户信息

通过orders关联查询用户使用user_id1个外键,只能关联查询出1条用户记录就能够使用内连接

 

SELECT

 orders.*,

 user.username,

 user.sex

FROM

 orders,

 USER

WHERE orders.user_id = user.id

2.3使用resultType实现

2.3.11对1查询映照的java对象

 

这里输出的结果包括 定单信息和用户信息,之前创建的pojo都是单表的实体类,所以这里需要自定义1个组合的pojo才能完成resultType的映照。

 

创建OrderCustom作为自定义pojo,补充相应的get()和set()方法

packagecn.itcast.mybatis.po;

 

 

public class OrderCustomextends Orders {

  

   //补充用户信息

   privateStringusername;

  

   privateStringsex;

  

   privateString address;

}

2.3.2 mapper.xml文件的配置

定义OrdersMapperCustom.xml文件,

   <!--1对1查询使用reusltType完成

   查询定单关联查询用户信息使用resultType的方式

    -->

    <selectid="findOrderUserList"resultType="orderCustom">

          SELECT

        orders.*,

        user.username,

        user.sex

      FROM

        orders,

        USER

      WHEREorders.user_id = user.id

    </select>

2.3.3 mapper.java接口

定义OrderMapperCustomer.java文件

packagecn.itcast.mybatis.mapper;

 

public interfaceOrdersMapperCustom {

   // 1对1查询,查询定单关联查询用户,使用resultType

   publicList<OrderCustom> findOrderUserList()throwsException;

}

2.3.4  测试OrdersMapperCustomerTest.java

package cn.itcast.mybatis.mapper;

 

public class OrdersMapperCustomTest {

 

         //会话工厂

         privateSqlSessionFactory sqlSessionFactory;

 

         //创建工厂

         @Before

         publicvoid init() throws IOException {

 

                   //配置文件(SqlMapConfig.xml)

                   Stringresource = "SqlMapConfig.xml";

 

                   //加载配置文件到输入流

                   InputStreaminputStream = Resources.getResourceAsStream(resource);

 

                   //创建会话工厂

                   sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);

 

         }

 

         @Test

         publicvoid testFindOrderUserList() throws Exception {

 

                   SqlSessionsqlSession = sqlSessionFactory.openSession();

                   //创建mapper代理对象

                   OrdersMapperCustomordersMapperCustom = sqlSession

                                     .getMapper(OrdersMapperCustom.class);

 

                   //调用方法

                   List<OrderCustom>list = ordersMapperCustom.findOrderUserList();

 

                   System.out.println(list);

         }

}

2.4    使用resultMap实现

2.4.1 resultMap映照思路

resultMap提供1对1关联查询的映照和1对多关联查询映照,1对1映照思路:将关联查询的信息映照到查询的POJO中,以下:

在Orders类中创建1个User属性,将关联查询的信息映照到User属性中。

Orders.java补充相应的get()和set()方法

package cn.itcast.mybatis.po;

 

public class Orders implements Serializable{

   private Integer id;

 

   private Integer userId;

 

   private String number;

 

   private Date createtime;

 

   private String note;

   

   //关联用户信息

private User user;

}

2.4.2  mapper.xml文件的配置

OrdersMapperCustomer.xml定义sql语句和resultMap映照之间的关系

<!-- 1对1查询resultMap,这里的ID是1个唯1的标识,与输出参数resultMap定义的相同(用黄色标出)

 -->

 

   <resultMaptype="orders"id="ordersUserResultMap">

      <!--完成了定单信息的映照配置-->

      <!--id:定单关联用户查询的唯1标识  -->

      <!--column: sql语句中查询的列,propertypojo中对应的属性-->

      <idcolumn="id"property="id"/>

      <resultcolumn="user_id"property="userId"/>

      <resultcolumn="number"property="number"/>

      <resultcolumn="createtime"property="createtime"/>

      <resultcolumn="note"property="note"/>

     

      <!--下边完成关联信息的映照

      association:用于对关联信息映照到单个pojo

      property:要将关联信息映照到orders的哪一个属性中

      javaType:关联信息映照到orders的属性的类型,是user的类型

       -->

      <associationproperty="user"javaType="user">

         <!--id:关联信息的唯1标识  -->

         <!--property要映照到user的哪一个属性中-->

         <idcolumn="user_id"property="id"/>

         <!--result就是普通列的映照-->

         <resultcolumn="username"property="username"/>

         <resultcolumn="sex"property="sex"/>

     

      </association>

     

   </resultMap>

<!-- 1对1查询使用reusltMap完成

   查询定单关联查询用户信息 -->

    <selectid="findOrderUserListResultMap"resultMap="ordersUserResultMap">

          SELECT

        orders.*,

        user.username,

        user.sex

      FROM

        orders,

        USER

      WHEREorders.user_id = user.id

    </select>

2.4.3  mapper.java接口

OrderMapperCustomer.java中添加使用resultMap进行1对1查询的接口

packagecn.itcast.mybatis.mapper;

 

public interfaceOrdersMapperCustom {

   // 1对1查询,使用resultMap

publicList<Orders> findOrderUserListResultMap()throwsException;

}

2.4.4  测试OrdersMapperCustomerTest.java

package cn.itcast.mybatis.mapper;

 

public class OrdersMapperCustomTest {

 

         //会话工厂

         privateSqlSessionFactory sqlSessionFactory;

 

         //创建工厂

         @Before

         publicvoid init() throws IOException {

 

                   //配置文件(SqlMapConfig.xml)

                   Stringresource = "SqlMapConfig.xml";

 

                  // 加载配置文件到输入流

                   InputStreaminputStream = Resources.getResourceAsStream(resource);

 

                   //创建会话工厂

                   sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);

 

         }

 

                   // 1对1查询使用resultMap

   @Test

   public voidtestFindOrderUserListResultMap() throwsException {

 

      SqlSessionsqlSession = sqlSessionFactory.openSession();

      // 创建mapper代理对象

      OrdersMapperCustomordersMapperCustom = sqlSession

            .getMapper(OrdersMapperCustom.class);

 

      // 调用方法

      List<Orders>list = ordersMapperCustom.findOrderUserListResultMap();

 

      System.out.println(list);

   }

}

2.5    小结

resultType:要自定义pojo 保证sql查询列和pojo的属性对应,加入sql语句使用别名,则查询不到该列的信息,这类方法相对较简单,所以利用广泛。

 

resultMap:使用association完成1对1映照需要配置1个resultMap,进程有点复杂,如果要实现延迟加载就只能用resultMap实现 ,如果为了方便对关联信息进行解析,也能够用association将关联信息映照到pojo中方便解析。

3       1对多查询

 

3.1     需求

 

使用mapper接口代理的方式查询所有定单信息(关联用户)及定单下的定单明细信息。

 

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进行1对多映照思路

 

resultMap 提供collection完成关联信息映照到集合对象中。

 

在orders类中创建集合属性:

package cn.itcast.mybatis.po;

 

public class Orders implements Serializable{

   private Integer id;

 

   private Integer userId;

 

   private String number;

 

   private Date createtime;

 

   private String note;

   

   //关联用户信息

    private User user;

   

   //定单明细

    privateList<Orderdetail> orderdetails;

}

3.4     mapper.xml文件的配置

<!-- 1对多,查询定单及定单明细 -->

   <resultMaptype="orders"id="orderAndOrderDetails"extends="ordersUserResultMap">

      <!--映照定单信息,和用户信息,这里使用继承ordersUserResultMap-->

     

      <!--映照定单明细信息

      property:要将关联信息映照到orders的哪一个属性中

      ofType:集合中pojo的类型

      -->

      <collectionproperty="orderdetails"ofType="cn.itcast.mybatis.po.Orderdetail">

         <!--id:关联信息定单明细的唯1标识

         propertyOrderdetail的属性名

           -->

         <idcolumn="orderdetail_id"property="id"/>

         <resultcolumn="items_num"property="itemsNum"/>

         <resultcolumn="items_id"property="itemsId"/>

      </collection>

  

   </resultMap>

<!-- 1对多查询使用reusltMap完成

   查询定单关联查询定单明细

    -->

    <selectid="findOrderAndOrderDetails"resultMap="orderAndOrderDetails">

         SELECT

     orders.*,

     user.username,

     user.sex ,

     orderdetail.id orderdetail_id,

     orderdetail.items_num,

     orderdetail.items_id

   FROM

     orders,

     USER,

     orderdetail

   WHEREorders.user_id = user.id  AND orders.id =orderdetail.orders_id

    </select>

3.5     mapper.java接口

在OrderMapperCustomer.java中添加使用resultMap进行1对多查询的接口

packagecn.itcast.mybatis.mapper;

 

public interfaceOrdersMapperCustom {

   // 1对多查询,使用resultMap

   publicList<Orders> findOrderAndOrderDetails()throwsException;

}

3.6     测试OrdersMapperCustomerTest.java

package cn.itcast.mybatis.mapper;

 

public class OrdersMapperCustomTest {

 

         //会话工厂

         privateSqlSessionFactory sqlSessionFactory;

 

         //创建工厂

         @Before

         publicvoid init() throws IOException {

 

                   //配置文件(SqlMapConfig.xml)

                   Stringresource = "SqlMapConfig.xml";

 

                   //加载配置文件到输入流

                   InputStreaminputStream = Resources.getResourceAsStream(resource);

 

                   //创建会话工厂

                   sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream);

 

         }

------分隔线----------------------------

上一篇 3D Touch

下一篇 经典C算法收藏

------分隔线----------------------------

最新技术推荐