mybatis连载(2)

mybatis高级查询

一对一查询

背景:现在有如下两张表,一张用户表(user)一张订单表(orders),因为一个用户可以有多个订单,所以用户表对订单表是一对多的关系;而订单对用户则是一对一的关系,在订单表中有用户表的外键uid,此外键指向用户表的主键id。

这里写图片描述

对应的User实体类:

public class User {
    private long uid ;
    private String username ;
    private String password ;
    private String name ;
    private String email ;
    private String phone ;
    private String addr ;
    private int state ;
    private String code; 
//省略setter getter方法

对应的Order实体类:

public class Orders {
    private long oid;
    private double total;
    private Date orderTime;
    private int state; 
//省略setter getter方法

需求:查询主表Orders,关联查询User表。(一个订单属于一个用户)
主表:Orders
关联查询表:User
sql:

select orders.*,user.username,user.name,user.addr from orders,user where orders.uid = user.uid;

这里写图片描述

这里只关联User表查询username,name,addr三个属性。

1.使用resultType输出映射
因为使用resultType进行输出映射有个特点:就是从数据库查询出的列名要和映射到的pojo类的属性值一致。
这下该怎么办呢?Orders实体类中没有User实体类中的属性,User实体类中也没有Orders类中的属性。
解决办法:新建一个OrdersPojo继承Orders类,并在这个类中扩展username,name,addr这三个要查询的属性。
这里你肯定要问了,为什么要新建一个类?为什么要继承Orders类?
因为我们输出的pojo对象需要包括sql查询出的属性,这两个实体类中都没有完全包含这些输出属性,所以要新建一个pojo类来接收输出映射。继承Orders类的原因是因为主要查询的是Orders类,关联查询出的user类属性少,所以为了方便才继承Orders类。

OrderPojo 类映射输出类:

public class OrderPojo extends Orders{
    private String username ;
    private String name ;
    private String addr ;
//省略setter getter方法

接下来要编写mapper.xml配置文件

<mapper namespace="com.mybatis.pojo.dao.OrderPojoDao">

    <select id="queryOrders" resultType="com.mybatis.pojo.OrderPojo">
        select orders.*
        ,user.username,user.name,user.addr
        from orders,user where orders.uid =
        user.uid;
    </select>

</mapper>

Namespace指向mapper.java接口,输出映射是OrderPojo类

mapper接口:

public interface OrderPojoDao {

    /***
     * resultType:根据订单表管理查询用户表
     */
    public List<OrderPojo> queryOrders();

}

注意:
1.namespace要是mapper.java接口的全路径.
2.id是方法名
3.输出映射是方法的返回值类型,这里用List,mybatis动态代理会自动调用selectList方法
4.输入映射是方法的参数,这里没有输入的参数,所以不用写。

测试类:

// 声明SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = null;

    @Before
    public void initFactory() throws Exception {
        String resource = "sqlMapConfig.xml";
        // 读取配置文件
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 创建会话工厂
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }


    /***
     * 测试resultType
     */
@Test
    public void queryOrdersTest() {
        // 声明SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrderPojoDao orderPojoDao = sqlSession.getMapper(OrderPojoDao.class);
        List<OrderPojo> list = orderPojoDao.queryOrders();
        System.out.println(list.toString());
        sqlSession.close();
    }

输出结果:

这里写图片描述

框住的是新增的三个属性,并且都映射到了值;如图可见总共查询出8条记录,和上面sql查询结果一致,并且属性也都全部成功映射。

2.使用resultMap映射输出
目标:使用resultMap把映射结果映射到Orders类中。

1.因为映射到Orders类中,所以不用新建pojo类
2.因为查询关联user表,所以要在Orders类中添加User属性

Orders类:

public class Orders {
    private long oid;
    private double total;
    private Date orderTime;
    private int state;

    // 关联User类
        private User user;
    //省略setter getter
}

这里主要使用resultMap规则:
1.先定义resultMap
2.输出类型是resultMap

配置文件:mapper.xml:

<!-- resultMap映射 -->
    <resultMap type="com.mybatis.shopping.Orders" id="queryByResultMap">
        <!-- 配置订单信息 -->
        <id column="oid" property="oid" />
        <result column="total" property="total" />
        <result column="orderTime" property="orderTime" />
        <result column="state" property="state" />

        <!-- 配置映射的关联用户信息 -->
        <association property="user" javaType="com.mybatis.shopping.User">
            <id column="uid" property="uid" />
            <result column="username" property="username" />
            <result column="name" property="name" />
            <result column="addr" property="addr" />
        </association>
    </resultMap>

    <select id="queryOrdersResultMap" resultMap="queryByResultMap">
        select orders.*
        ,user.username,user.name,user.addr
        from orders,user where orders.uid =
        user.uid;
    </select>

association 用来映射单个pojo对象。

Mappper.java接口:

    /***
     * resultMap:根据订单表管理查询用户表
     */
    public List<Orders> queryOrdersResultMap();

测试类:

    @Test
    public void queryOrdersResultMapTest() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrderPojoDao orderPojoDao = sqlSession.getMapper(OrderPojoDao.class);
        List<Orders> orderList = orderPojoDao.queryOrdersResultMap();

        System.out.println(orderList);
    }

这里写图片描述

由图可见,user属性已经被成功映射。
查询到的同样是8条数据,由图可见,username,name,addr都成功映射到user属性中了。

总结
ResultType:使用比较简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,才可完成映射。
ResultMap:需要单独定义,如果对查询结果又特殊要求,使用resultMap可以完成将管理查询映射到pojo属性中。
ResultMap可以实现延迟加载,resultType不能实现。

高级映射一对多

需求:查询订单及订单明细的信息。
主查询表:订单表
关联查询表:订单明细表
用户表和订单表的关系是一对多,订单表和订单明细表的关系也是一对多。现在以订单表为主表关联查询用户表和订单明细表。

sql:

select
        orders.* ,user.username,user.addr,user.name,
        orderitem.itemid,orderitem.count,orderitem.subtotal
        from orders,user,orderitem where
        orders.uid = user.uid and orderitem.oid
        = orders.oid;

这里写图片描述

如图,查询主表orders关联查询user表和orderitem表的结果。
由图知道oid总共有三行,说明对应三个订单详情,而且oid=2的订单total是1849,恰好是三个订单项的subtotal的总和。
现在要求把订单项映射输出到ordes实体中,并映射成集合。
那么就需要在orders表中定义订单项的集合。

Oders.java:

public class Orders {
    private long oid;
    private double total;
    private Date orderTime;
    private int state;

    // 关联User类
    private User user;

    // 订单项集合
    private List<OrderItem> orderItems;

接下来编写mappe.xml程序:
由于是一对多的高级映射,这里采用resultMap的形式输出

<resultMap type="com.mybatis.shopping.Orders" id="queryOrdersAndOrderItem">
        <!-- 配置订单信息 -->
        <id column="oid" property="oid" />
        <result column="total" property="total" />
        <result column="orderTime" property="orderTime" />
        <result column="state" property="state" />

        <!-- 配置用户信息 -->
        <association property="user" javaType="com.mybatis.shopping.User">
            <id column="uid" property="uid" />
            <result column="username" property="username" />
            <result column="name" property="name" />
            <result column="addr" property="addr" />
        </association>
        <!-- 配置订单条目集合信息 -->
        <collection property="orderItems" ofType="com.mybatis.shopping.OrderItem">
            <id column="itemid" property="itemid" />
            <result column="count" property="count" />
            <result column="subtotal" property="subtotal" />
        </collection>

    </resultMap>


<!-- 查询订单表,用户,订单明细表 -->
    <select id="queryOrdersAndOrderItemAndUser" resultMap="queryOrdersAndOrderItem">
        select
        orders.* ,user.username,user.addr,user.name,
        orderitem.itemid,orderitem.count,orderitem.subtotal
        from orders,user,orderitem where
        orders.uid = user.uid and orderitem.oid
        = orders.oid;
    </select>

collection :映射到集合。

Mapper.java接口

public List<Orders> queryOrdersAndOrderItemAndUser();

测试类:

@Test
    public void queryOrdersAndOrderItemAndUserTest() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrderPojoDao orderPojoDao = sqlSession.getMapper(OrderPojoDao.class);
         List<Orders> list = orderPojoDao.queryOrdersAndOrderItemAndUser();
        System.out.println(list);
    }

输出:

这里写图片描述

有图可见,orderitem属性和user属性都被映射到了。

高级查询之多对多查询

需求:查询用户表购买的商品。
分析:因为用户和商品并没有直接关系,所以要查询用户购买的所有商品,则需要通过用户表和订单表的关系(一对多),订单表和订单项表的关系(一对多),订单项表和商品表的关系(一对一)来关联查询商品。

Sql语句:

select user.name,user.addr,orders.orderTime,orders.total,orders.oid,orderitem.itemid,orderitem.count,orderitem.subtotal,product.pid,product.pname,product.pdesc,product.shop_price
from orders,user,orderitem,product where orders.uid = user.uid and orders.oid = orderitem.oid and product.pid = orderitem.pid;

如下是查询结果:

这里写图片描述‘’

需求:将查询到的结果集映射到User中输出。
什么意思呢,就是输出映射的pojo类型是User。
分析:由于我们知道用户表对订单表是一对多,要想把订单表信息映射到用户表中,则要在用户表中在添加一个订单表的集合;同理订单表对订单项是一对多,因此在订单表中也要添加订单项表的集合;因为订单项对商品是一对一,所以在订单项表中添加商品的引用,对应到mapper.xml中的association.

User.java:

public class User {

    private long uid ;
    private String username ;
    private String password ;
    private String name ;
    private String email ;
    private String phone ;
    private String addr ;
    private int state ;
    private String code;

    //订单表集合
    private List<Orders> orders;
    //省略setter getter

在Orders中添加orderIiem的集合

// 订单项集合
    private List<OrderItem> orderItems;

在orderIiem中添加product的对象(他俩一对一)

orderIiem.java

public class OrderItem {
    private long itemid;
    private int count;
    private double subtotal;

    // 商品
    private Product product;
    //省略setter getter方法

mapper.xml:

<!-- 查询用户购买的商品 -->
    <select id="queryUserAndProduct" resultMap="queryUserAndProductResultMap" >
        select
        user.name,user.addr,orders.orderTime,orders.total,orders.oid,orderitem.itemid,orderitem.count,orderitem.subtotal,product.pid,product.pname,product.pdesc,product.shop_price
        from orders,user,orderitem,product where orders.uid = user.uid and
        orders.oid = orderitem.oid and product.pid = orderitem.pid;
    </select>

    <!-- 输出类型是user -->
    <resultMap type="com.mybatis.shopping.User" id="queryUserAndProductResultMap">
        <id column="uid" property="uid" />
        <result column="name" property="name" />
        <result column="addr" property="addr" />

        <collection property="orders" ofType="com.mybatis.shopping.Orders">
            <id column="oid" property="oid" />
            <result column="orderTime" property="orderTime" />
            <result column="total" property="total" />

            <!-- 嵌套collocation -->
            <collection property="orderItems" ofType="com.mybatis.shopping.OrderItem">
                <id column="itemid" property="itemid" />
                <result column="count" property="count" />
                <result column="subtotal" property="subtotal" />
                <result column="count" property="count" />

                <association property="product" javaType="com.mybatis.shopping.Product">
                    <id column="pid" property="pid" />
                    <result column="pname" property="pname" />
                    <result column="pdesc" property="pdesc" />
                    <result column="shop_price" property="shop_price" />
                </association>
            </collection>
        </collection>

    </resultMap>

mapper.java:

public List<User> queryUserAndProduct();

测试:

@Test
    public void queryUserAndProductTest() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrderPojoDao orderPojoDao = sqlSession.getMapper(OrderPojoDao.class);
        List<User> userList = orderPojoDao.queryUserAndProduct();
        System.out.println(userList);
    }

这里写图片描述

成功映射

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值