zoukankan      html  css  js  c++  java
  • mybatis 高级映射

    高级映射主要还是映射,只是映射中的数据关系复杂了,其中就包括一对一、一对多、多对多的关系。

    说到映射就想到mapper.xml文件

    说到关系想到一对一、一对多、多对多

    一对一、一对多、多对多就是查询结果,这样的话mapper.xml中对应查询结果的就是resultType和resultMap。

    一对一、一对多、多对多会有什么样的结果?

    一对一:一张表一条数据对应关联表一条数据

    一对多:一张表一条数据对应关联表多条数据

    多对多:一张表多条数据对应关联表多条数据

    下面看看resulType、resultMap分别如何实现上面一对一、一对多、多对多结果集

    一、resulType

      Ⅰ、一对一

        1、Mapper.xml

        <select id="findOrdersUser" resultType="">
            SELECT 
              orders.*,
              t_user.*
            FROM
              orders,
              t_user
            WHERE orders.user_id = t_user.id 
        </select>

        resultType的值要包含orders、t_user的内容的返回类型,需要在Orders类型的基础上扩展一个User结构的扩展类

        2、设置Orders属性

    public class Orders {
            private Integer id;
        private Integer userId;
        private String number;
        private Date createtime;
        private String note;

        3、设置OrdersExtend属性

    public class OrdersExtend extends Orders {
        private Integer id;
        private String username;// 用户姓名
        private String sex;// 性别
        private Date birthday;// 生日
        private String address;// 地址

        所以resultType配置

        <select id="findOrdersUser" resultType="com.xxx.mybatis.po.OrdersExtend">
            SELECT 
              orders.*,
              t_user.*
            FROM
              orders,
              t_user
            WHERE orders.user_id = t_user.id 
        </select>

        4、OrdersMapper.java

    public interface OrdersMapper {
        public OrdersExtend findOrdersUser();
    }

        5、编写测试

        SqlSessionFactory sqlSessionFactory;
    
        @BeforeEach
        public void setUp() throws Exception {
        // mybatis核心配置文件
        String resource = "SqlMapConfig.xml";
        // 核心配置文件流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 根据核心配置文件,创建SqlSessionFactory对象
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }
    
        @Test
       public void testFindOrdersUser() {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        OrdersMapper ordersMapper=sqlSession.getMapper(OrdersMapper.class);
        List<OrdersExtend> list=ordersMapper.findOrdersUser();
        System.out.println(list);
        }

        6、测试结果:发现和sql数据库查出的数据不一致(id为null)

    [
    Orders [id=null, user_Id=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null]
    OrdersExtend [id=1, username=zhangsan, sex=2, birthday=Thu Jul 10 00:00:00 CST 2014, address=tianji]
    , 
    Orders [id=null, user_Id=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null]
    OrdersExtend [id=2, username=zhangsan, sex=2, birthday=Thu Jul 10 00:00:00 CST 2014, address=tianji]
    ]

        使用resultType需要定义符合查询结果的类型,如果查询结果中有字段名一样时,会出现有一个字段为null的结果,当然可以使用别名解决,

          例如上例中的Orders中的id

            1、将配置文件中的sql语句中select *换成 select 字段名

    <select id="findOrdersUser"    resultType="com.xxx.mybatis.po.OrdersExtend">
            SELECT
                orders.id AS order_id
                ,orders.user_id
                ,orders.number
                ,orders.createtime
                ,orders.note
                ,t_user.*
            FROM
                orders,
                t_user
            WHERE orders.user_id = t_user.id
        </select>

            2、修改Orders类型中id字段名 

    public class Orders {
            private Integer id order_id;

      Ⅱ、一对多

        1、配置Mapper.xml

        <select id="findOrdersAndOrderDetail" resultType="com.xxx.mybatis.po.OrdersExtend">
            SELECT 
                orders.id AS order_id,
                orders.user_id,
                orders.number,
                orders.createtime,
                orders.note,
                t_user.*
                orderdetail.id orderdetail_id,
                orderdetail.items_id,
                orderdetail.items_num,
                orderdetail.orders_id
            FROM
              orders,
              USER,
              orderdetail
            WHERE orders.user_id = user.id AND orderdetail.orders_id=orders.id
        </select>

        2、Mapper.java

    public interface OrdersMapper {
        public List<OrdersExtend> findOrdersUser();
        
        public List<OrdersExtend> findOrdersAndOrderDetail();
    }

        3、增加OrdersExtend属性

    public class OrdersExtend extends Orders {
        private String username;// 用户姓名
        private String address;// 地址
        
        private Integer id orderdetail_id;
        private Integer items_id;
        private Integer items_num;
        private Integer orders_id;

        4、测试代码

       public void testFindOrdersAndOrderDetail() {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        OrdersMapper ordersMapper=sqlSession.getMapper(OrdersMapper.class);
        List<OrdersExtend> list=ordersMapper.findOrdersAndOrderDetail();
        System.out.println(list);
        }

        5、测试结果(Orders的数据有重复)

    [Orders [id=1, user_Id=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null]
    OrdersExtend [username=zhangsan, address=tianji, orderdetail_id=1, items_id=1, items_num=1, orders_id=1], 
    
    Orders [id=1, user_Id=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null]
    OrdersExtend [username=zhangsan, address=tianji, orderdetail_id=2, items_id=2, items_num=3, orders_id=1], 
    
    Orders [id=2, user_Id=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null]
    OrdersExtend [username=zhangsan, address=tianji, orderdetail_id=3, items_id=3, items_num=4, orders_id=2], 
    
    Orders [id=2, user_Id=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null]
    OrdersExtend [username=zhangsan, address=tianji, orderdetail_id=4, items_id=2, items_num=3, orders_id=2]]

      Ⅲ、多对多

        要以用户为主查询,用户和商品是多对多的关系,一个用户可以购买多种商品,一种商品可以被多个用户购买

        1、配置Mapper.xml

        <select id="findManytoMany"
            resultType="com.xxx.mybatis.po.UserExtend">
            SELECT
            t_user.*,
            orders.number,
            orders.createtime ordercreatetime,
            orderdetail.items_num itemsid,
            orderdetail.orders_id ordersId,
            items.name items_name,
            items.detail items_detail,
            items.price items_price
            FROM
            orders,
            t_user,
            orderdetail,
            items
            WHERE orders.user_id = t_user.id AND orderdetail.orders_id=orders.id
            AND orderdetail.items_id = items.id
        </select>

        2、Mapper.java

    public List<UserExtend> findManytoMany();

        3、创建UserExtend

    public class UserExtend extends User {
        //订单属性
        private String number;
        private Date ordercreatetime;
        //订单明细
        private Integer ordersId;
        private Integer itemsId;
        //商品
        private String item_name;
        private Double item_price;
        private String item_detail;

        4、测试代码

        @Test
       public void testFindManytoMany() {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        List<UserExtend> list=mapper.findManytoMany();
        System.out.println(list);
        }

        5、测试结果

    [User [id=1, username=zhangsan, sex=2, birthday=Thu Jul 10 00:00:00 CST 2014, address=tianji]
    UserExtend [number=1000010, ordercreatetime=Wed Feb 04 13:22:35 CST 2015, ordersId=1, itemsId=1, item_name=null, item_price=null, item_detail=null], 
    
    User [id=1, username=zhangsan, sex=2, birthday=Thu Jul 10 00:00:00 CST 2014, address=tianji]
    UserExtend [number=1000010, ordercreatetime=Wed Feb 04 13:22:35 CST 2015, ordersId=1, itemsId=3, item_name=null, item_price=null, item_detail=null], 
    
    User [id=1, username=zhangsan, sex=2, birthday=Thu Jul 10 00:00:00 CST 2014, address=tianji]
    UserExtend [number=1000011, ordercreatetime=Tue Feb 03 13:22:41 CST 2015, ordersId=2, itemsId=4, item_name=null, item_price=null, item_detail=null], 
    
    User [id=1, username=zhangsan, sex=2, birthday=Thu Jul 10 00:00:00 CST 2014, address=tianji]
    UserExtend [number=1000011, ordercreatetime=Tue Feb 03 13:22:41 CST 2015, ordersId=2, itemsId=3, item_name=null, item_price=null, item_detail=null]]

      总结:

        1、resultType的映射类型(xxxExtend)的属性会随着查询的项目的变化而变化

        2、查询字段名和参数类型的字段名要一致

        3、多表查询字段名不能相同,相同的话要用别名区分

        4、resultType比较适用于单表查询,或不需要新增太多属性的查询

    二、resulMap

      Ⅰ、一对一

        1、配置Mapper.xml

        <select id="findOrdersUserResultMap" resultMap="">
            SELECT
            orders.*,
            t_user.*
            FROM
            orders,
            t_user
            WHERE
            orders.user_id = t_user.id
        </select>

        resultMap需要指定Map,那么就需要创建一个Map给它

        2、创建Map,指定映射关系

          2.1、创建返回参数类型

    public class OrdersExtendResultMap extends Orders {
        private User user;

          2.2、创建resultMap

    <!-- 
        type:查询结果映射类型
        id:resultMap区分,指定查询结果要使用哪个映射Map
     -->
    <resultMap type="com.xxx.mybatis.po.OrdersExtendResultMap" id="OrdersUserResultMap">
        <!-- 
            id:指定查询列中的唯一标识,如果有多个列组成唯一标识那就配置多个id
            column:查询字段名(select id,user_id,number,createtime,note)
            property:映射类型(OrdersExtendResultMap)的属性名
         -->
        <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:用于映射关联查询单个对象的信息(一对一映射)
            property:映射类型(OrdersExtendResultMap)的属性名
            javaType:映射类型(OrdersExtendResultMap)的属性名的类型
        -->
        <association property="user" javaType="com.xxx.mybatis.po.User">
            <!-- 
                id:指定查询列中的唯一标识,如果有多个列组成唯一标识那就配置多个id
                column:查询字段名(select user_id,username,sex,address)
                property:映射类型(OrdersExtendResultMap)的属性名
             -->
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>

        3、将创建的resultMap的id赋值给statement的resultMap

        <select id="findOrdersUserResultMap" resultMap="OrdersUserResultMap">
            SELECT
            orders.*,
            t_user.*
            FROM
            orders,
            t_user
            WHERE
            orders.user_id = t_user.id
        </select>

        4、Mapper.java

    public List<OrdersExtendResultMap>  findOrdersUserResultMap();

        5、测试代码

        @Test
       public void testFindOrdersUserResultMap() {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        OrdersMapper ordersMapper=sqlSession.getMapper(OrdersMapper.class);
        List<OrdersExtendResultMap> list=ordersMapper.findOrdersUserResultMap();
        System.out.println(list);
        }

        6、测试结果(birthday=null是因为没有做映射)

    [Orders [id=1, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null]
    OrdersExtendResultMap [user=User [id=1, username=zhangsan, sex=2, birthday=null, address=tianji]], 
    Orders [id=2, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null]
    OrdersExtendResultMap [user=User [id=1, username=zhangsan, sex=2, birthday=null, address=tianji]]]

      Ⅱ、一对多

        1、OrderDetail

    public class Orderdetail {
        private Integer id;
        private Integer ordersId;
        private Integer itemsId;

        2、Mapper.xml

        <!-- 使用extends继承,不用在中配置订单信息和用户信息的映射 -->
        <resultMap type="com.xxx.mybatis.po.OrdersExtendResultMap" id="OntoManyResultMap" extends="OrdersUserResultMap">
            <collection property="orderdetails" ofType="com.xxx.mybatis.po.Orderdetail">
                <!-- id:订单明细唯 一标识 property:要将订单明细的唯 一标识 映射到cn.itcast.mybatis.po.Orderdetail的哪个属性 -->
                <id column="orderdetail_id" property="id" />
                <result column="items_id" property="itemsId" />
                <result column="items_num" property="itemsNum" />
                <result column="orders_id" property="ordersId" />
            </collection>
        </resultMap>

        3、OrdersExtendResultMap添加属性

    public class OrdersExtendResultMap extends Orders {
        private User user;
        
        private List<Orderdetail> orderdetails;

        4、配置statement

        <select id="findOnetoMany" resultMap="OntoManyResultMap">
            SELECT
            orders.*,
            t_user.username,
            t_user.sex,
            t_user.address,
            orderdetail.id
            orderdetail_id,
            orderdetail.items_id,
            orderdetail.items_num,
            orderdetail.orders_id
            FROM
            orders,
            t_user,
            orderdetail
            WHERE orders.user_id
            = t_user.id AND orderdetail.orders_id=orders.id
        </select>

        5、接口方法

    public List<OrdersExtendResultMap>  findOnetoMany();

        6、测试代码

        @Test
       public void testFindOnetoMany() {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        OrdersMapper ordersMapper=sqlSession.getMapper(OrdersMapper.class);
        List<OrdersExtendResultMap> list=ordersMapper.findOnetoMany();
        System.out.println(list);
        }

        7、测试结果

    [Orders [id=1, userId=1, number=1000010, createtime=Wed Feb 04 13:22:35 CST 2015, note=null]
    OrdersExtendResultMap
    [
    user=User [id=1, username=zhangsan, sex=2, birthday=null, address=tianji], 
    orderdetails=
    [
    Orderdetail [id=1, ordersId=1, itemsId=1, itemsNum=1], 
    Orderdetail [id=2, ordersId=1, itemsId=2, itemsNum=3]]], 
    
    Orders [id=2, userId=1, number=1000011, createtime=Tue Feb 03 13:22:41 CST 2015, note=null]
    OrdersExtendResultMap 
    [
    user=User [id=1, username=zhangsan, sex=2, birthday=null, address=tianji], orderdetails=
    [
    Orderdetail [id=3, ordersId=2, itemsId=3, itemsNum=4], 
    Orderdetail [id=4, ordersId=2, itemsId=2, itemsNum=3]]]]

      Ⅲ、多对多

        1、一个用户有多个订单

    public class UserExtendResultMap extends User {
        private List<OrdersExtendResultMap> orders;

        2、一个订单有多个订单明细

    public class OrdersExtendResultMap extends Orders {
        
        private List<OrderdetailExtendResultMap> orderdetails;

        3、一个明细有多种商品

    public class OrderdetailExtendResultMap extends Orderdetail {
        private List<Items> items;

        4、商品

    public class Items {
        private Integer id;
        private String name;
        private Double price;
        private String detail;
        private String pic;
        private Date createtime;

        5、配置statement(注意唯一标识--id),如果有唯一标识相同的话会出现数据列表只读一条记录

        <select id="findManytoManyResultMap" resultMap="ManytoManyresultMap">
            SELECT
            t_user.*,
            orders.id oid,
            orders.user_id,
            orders.number,
            orders.createtime,
            orders.note,
            orderdetail.id odid,
            orderdetail.items_id,
            orderdetail.items_num,
            orderdetail.orders_id,
            items.id iid,
            items.name items_name,
            items.detail items_detail,
            items.price items_price
            FROM
            orders,
            t_user,
            orderdetail,
            items
            WHERE orders.user_id = t_user.id AND orderdetail.orders_id=orders.id
            AND orderdetail.items_id = items.id
        </select>

        6、配置resultMap

    <resultMap type="com.xxx.mybatis.po.UserExtendResultMap" id="ManytoManyresultMap">
                <id column="id" property="id" />
                <result column="username" property="username" />
                <result column="sex" property="sex" />
                <result column="address" property="address" />
                
             <!-- 一个用户有多个订单  -->
            <collection property="orders" ofType="com.xxx.mybatis.po.OrdersExtendResultMap">
                <id column="oid" 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="com.xxx.mybatis.po.OrderdetailExtendResultMap">
                    <id column="odid" property="id" />
                    <result column="items_id" property="itemsId" />
                    <result column="items_num" property="itemsNum" />
                    <result column="orders_id" property="ordersId" />
                    
                    <!-- 一个订单明细有一个商品 -->
                    <association property="items" javaType="com.xxx.mybatis.po.Items">
                        <id column="iid" property="id" />
                        <result column="name" property="name" />
                        <result column="detail" property="detail" />
                        <result column="price" property="price" />
                    </association>
                </collection> 
            </collection> 
        </resultMap>

        7、接口方法

    public List<UserExtendResultMap> findManytoManyResultMap();

        8、测试代码

        @Test
       public void testFindManytoManyResultMap() {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        List<UserExtendResultMap> list=mapper.findManytoManyResultMap();
        System.out.println(list);
        }

        9、测试结果

    [UserExtendResultMap [
        orders=[
            OrdersExtendResultMap [
                orderdetails=[
                    OrderdetailExtend [
                        items=Items [id=1, name=null, price=null, detail=null, pic=null, createtime=null]], 
                    OrderdetailExtend [
                        items=Items [id=2, name=null, price=null, detail=null, pic=null, createtime=null]]]], 
            OrdersExtendResultMap [
                orderdetails=[
                    OrderdetailExtend [
                        items=Items [id=3, name=null, price=null, detail=null, pic=null, createtime=null]], 
                    OrderdetailExtend [
                        items=Items [id=2, name=null, price=null, detail=null, pic=null, createtime=null]]]]]]]

    总结:

      resultType:将查询结果按照sql列名pojo属性名一致性映射到pojo中

      resultMap:使用association和collection完成高级映射(对结果有特殊的映射要求)

      association:一对一关系映射

          将关联查询信息映射到一个pojo对象中

      collection:将关联查询信息映射到一个list集合中

  • 相关阅读:
    在C#代码中应用Log4Net(二)典型的使用方式
    在C#代码中应用Log4Net(一)简单使用Log4Net
    Windows Azure Active Directory (2) Windows Azure AD基础
    Windows Azure Virtual Network (6) 设置Azure Virtual Machine固定公网IP (Virtual IP Address, VIP) (1)
    Windows Azure Active Directory (1) 前言
    Azure China (6) SAP 应用在华登陆 Windows Azure 公有云
    Microsoft Azure News(3) Azure新的基本实例上线 (Basic Virtual Machine)
    Microsoft Azure News(2) 在Microsoft Azure上运行SAP应用程序
    Microsoft Azure News(1) 新的数据中心Japan East, Japan West and Brazil South
    Windows Azure HandBook (2) Azure China提供的服务
  • 原文地址:https://www.cnblogs.com/WarBlog/p/14931813.html
Copyright © 2011-2022 走看看