• 高级映射,查询缓存和与spring整合


    一、高级映射

    -------一对一

    这里以订单查询为例,其中有一个外键为user_id,通过这个关联用户表。这里要实现的功能是这个两个表关联查询,得到订单的信息和部分user的信息。order表结构如下图:

    1.这里先介绍一对一的关联查询。原始的order.java不能映射全部字段,需要新创建pojo。所以创建一个OrderCustom的pojo。

    package entity;
    
    public class OrderCustom extends Order{
        private String username;
        private String sex;
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        
    
    }

     2.后面就是按步骤创建OrderMaper和其对应的配置文件

    因为此处在sqlmapConfig中打算使用批量类加载的方式,所以要把maper类和对应的配置文件放在同一个包中

    OrderCustomerMapper .java的代码如下:

    package mapper;
    
    import java.util.List;
    
    import entity.Order;
    import entity.OrderCustom;
    
    public interface OrderCustomerMapper {
        public List<OrderCustom> findOrder() throws Exception;
    
    }

    OrderCustomerMapper .xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--mapper代理开发,namespace要与mapper接口的全名地址一样-->
    
    <mapper namespace="mapper.OrderCustomerMapper">
    <resultMap id="orderResultMap" type="entity.Order">
    
        <select id="findOrder"  resultType="OrderCustom">
            SELECT o.*,u.username,u.sex from users u,orders o
            WHERE u.id=o.user_id
        </select>
        
    
    </mapper>

    以上都做好了后可以用Junit测试了:

    测试代码

    package mapper;
    
    import java.io.InputStream;
    import java.util.List;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Before;
    import org.junit.Test;
    
    import entity.Order;
    import entity.OrderCustom;
    
    public class OrderTest {
        private SqlSessionFactory sqlSessionFactory;
    
        @Before
        public void setUp() throws Exception {
            String resource="SqlMapConfig.xml";
            InputStream stream=Resources.getResourceAsStream(resource);
            sqlSessionFactory=new SqlSessionFactoryBuilder().build(stream);
        }
    
        @Test
        public void testFindOrder() throws Exception {
            SqlSession sqlSession=sqlSessionFactory.openSession();
            OrderCustomerMapper ordermapper=sqlSession.getMapper(OrderCustomerMapper.class);
            List<OrderCustom> orderCustom=ordermapper.findOrder();
            sqlSession.close();
            
        }
    
            
        }
    
    }

    以上是用的resultType方式返回的结果集,其实还有resultMap的方式返回结果集。下面介绍如何使用resultMap来实现。

    1.resultMap是不需要再创建一个OrderCustom的pojo的,只需要在Order类中加一个User类定义的user属性即可,并加上这个属性的get set方法。

    然后在OrderCustomerMapper .xml中添加resultMap标签映射,添加后的OrderCustomerMapper .xml如下:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <!--mapper代理开发,namespace要与mapper接口的全名地址一样-->
    
    <mapper namespace="mapper.OrderCustomerMapper">
    <resultMap id="orderResultMap" type="entity.Order">
    <!-- 配置映射的订单信息 -->
        <id column="id" property="id"/>
        <result column="user_id" property="user_id"/>
        <result column="createTime" property="createTime"/>
        <result column="note" property="note"/>
        <!-- 配置映射的关联用户信息 -->
        
        <!-- 关联查询出的一个对象 -->
        
        <!-- property:将关联查询的用户信息映射到哪个属性中去 -->
        <association property="user" javaType="entity.users">
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            
        </association>
         
    
    </resultMap>
    
        <select id="findOrder"  resultType="OrderCustom">
            SELECT o.*,u.username,u.sex from users u,orders o
            WHERE u.id=o.user_id
        </select>
        <select id="findOrderResultMap"  resultMap="orderResultMap">
            SELECT o.*,u.username,u.sex from users u,orders o
            WHERE u.id=o.user_id
        </select>
        
    
    </mapper>

    2.在OrderCustomerMapper 中添加一个接口来测试这个用resultMap

    public List<Order> findOrderResultMap() throws Exception;

    3.测试

    @Test
        public void testFindOrderResltMap() throws Exception {
            SqlSession sqlSession=sqlSessionFactory.openSession();
            OrderCustomerMapper ordermapper=sqlSession.getMapper(OrderCustomerMapper.class);
            List<Order> orderCustom=ordermapper.findOrderResultMap();
            sqlSession.close();
            
        }

    以上就介绍完了两种方式的一对一查询关联的使用,可以看出resultType的方式使用起来更简单,一般使用这个。当有某种特殊的需求不得不使用resultMap时才用这个。

    一对多的查询:

    查询订单及订单明细的方法。

    1.在mapper.xml中添加:

    <select id="findOrderAndDetail"  resultMap="orderAndItemDetail">
            SELECT o.*,u.username,u.sex,od.id as odrderdetai_id,od.item_id,od.order_id from users u,orders o,orderdetail od
            WHERE u.id=o.user_id AND o.id=od.order_id
        </select>

    <resultMap id="orderAndItemDetail" type="entity.Order" extends="orderResultMap">
    
        <!-- 因为一个订单对应多个订单详细,所以使用collection -->
         <collection property="orderDetail" ofType="entity.OrderDetail">
             <id column="odrderdetai_id" property="id"/>
             <result column="order_id" property="order_id"/>
             <result column="item_id" property="item_id"/>
         </collection>
    
    </resultMap>

    2.在mapper.java接口中添加方法:

    public List<Order> findOrderAndDetail() throws Exception;

    3.测试

    @Test
        public void testFindOrderAndDetail() throws Exception {
            SqlSession sqlSession=sqlSessionFactory.openSession();
            OrderCustomerMapper ordermapper=sqlSession.getMapper(OrderCustomerMapper.class);
            List<Order> orderCustom=ordermapper.findOrderAndDetail();
            sqlSession.close();
            
        }

    多对多的查询:

       多对多的映射方式与一对多的映射方式基本相同,它是一对多的一种情况。例如一个用户和商品类型就是多对多的,一个用户可以买多种商品,一个商品可以被多个用户购买。在User类中创建一个属性orderList<Order>,Oder表中加一个

    orderDetailList<OrderItem>属性,OrderItem表中增加一个属性item,这是类间的关系。那么使用ResultMap的时候,要在collection中再套着collection。

    二、延迟加载

    1.什么是延迟加载

    resultMap中的association和collection具有延迟加载的属性

    先从单标查询,需要时再从关联表中查询,

    2.使用association实现延迟加载

    1)mapper.xml中需要两个statement:

    a只查询订单信息:  select * from orders  在查询订单的statement中使用association去延迟加载下面的statement

    在association中有select和column连个属性。

    select:指定需要延迟加载的statement的ID(根据user_id查询user的statement),如果要找的statement不在本mapper中,需要在前面加上namespace

    column:订单信息中关联用户信息查询的列,是user_id。

    b关联查询用户信息:通过以上查询到的user_id去关联查询用户信息

    3.延迟加载配置

    mybatis默认是关闭延迟加载的,需要在SqlMapConfig.xml中setting中配置

    <settings>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLasyLoading" value="false">
    </settings>
  • 相关阅读:
    Encountered a section with no Package: header
    java的System.getProperty()方法能够获取的值
    谷歌技术&quot;三宝&quot;之MapReduce
    surfaceDestroyed什么时候被调用
    调用CachedRowSetImpl类时,为什么会出现这样的错误
    正則表達式举例(下)
    java中接口的定义与实现
    UVA 538
    编程算法
    3D空间包围球(Bounding Sphere)的求法
  • 原文地址:https://www.cnblogs.com/softzrp/p/7147980.html
Copyright © 2020-2023  润新知