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

原文地址:https://www.cnblogs.com/WarBlog/p/14931813.html