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集合中

  • 相关阅读:
    如何解决python连接数据库编码问题(python传数据到mysql乱码)'ascii' codec can't encode _mysql_exceptions.OperationalError: (1366, "Incorrect string value:?
    git 和 github 链接
    python 链接 redis 失败 由于目标计算机积极拒绝,无法连接
    假设检验,alpha,p值 通俗易懂的的理解。
    python 爬虫学习之路
    SQL邮件服务(解决各种疑难杂症)+案例 + 使用SQLserver 邮件系统发送SQL代理作业执行警告
    使用tomcat,不能连接localhost/8080的解决办法
    制作R中分词的字典的办法
    Windos 下python2.7安装 pymssql 解决方案
    R语言做相关性分析
  • 原文地址:https://www.cnblogs.com/WarBlog/p/14931813.html
Copyright © 2011-2022 走看看