Mybatis延迟查询

一对一延迟查询

  • 针对的是关联对象, 用户和订单从面相对象的角度来说就是关联对象,当只需要订单数据,尚不需要用户数据的时候,就不应该去查询用户表,啥时候用到用户数据,啥时候查询

原Mybatis查询

pojo

User.java

package com.ahu.pojo;

import java.util.Date;
import java.util.List;

/**
 * 一个用户对应多个订单
 */
public class User {
    
    

    private int id;
    private String username;
    private String sex;
    private Date birthday;
    private String address;
    private List<Orders> ordersList;

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    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;
    }

    public Date getBirthday() {
    
    
        return birthday;
    }

    public void setBirthday(Date birthday) {
    
    
        this.birthday = birthday;
    }

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }

    public List<Orders> getOrdersList() {
    
    
        return ordersList;
    }

    public void setOrdersList(List<Orders> ordersList) {
    
    
        this.ordersList = ordersList;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                ", address='" + address + '\'' +
                ", ordersList=" + ordersList +
                '}';
    }
}

Orders.java

package com.ahu.pojo;

import java.util.Date;

public class Orders {
    
    
    private Integer id;

    private Integer userId;

    private String number;

    private Date createtime;

    private String note;

    private User user;

    public Integer getId() {
    
    
        return id;
    }

    public void setId(Integer id) {
    
    
        this.id = id;
    }

    public Integer getUserId() {
    
    
        return userId;
    }

    public void setUserId(Integer userId) {
    
    
        this.userId = userId;
    }

    public String getNumber() {
    
    
        return number;
    }

    public void setNumber(String number) {
    
    
        this.number = number == null ? null : number.trim();
    }

    public Date getCreatetime() {
    
    
        return createtime;
    }

    public void setCreatetime(Date createtime) {
    
    
        this.createtime = createtime;
    }

	public String getNote() {
    
    
        return note;
    }

    public void setNote(String note) {
    
    
        this.note = note == null ? null : note.trim();
    }

    public User getUser() {
    
    
        return user;
    }

    public void setUser(User user) {
    
    
        this.user = user;
    }

    @Override
    public String toString() {
    
    
        return "Orders{" +
                "id=" + id +
                ", userId=" + userId +
                ", number='" + number + '\'' +
                ", createtime=" + createtime +
                ", note='" + note + '\'' +
                ", user=" + user +
                '}';
    }
}

配置文件

OrdersMapper.java

package com.ahu.mapper;

import com.ahu.pojo.Orders;

import java.util.List;

public interface OrdersMapper {
    
    
    /**
     *一对一查询,订单为基准查询用户
     * @return
     */
    List<Orders> queryOrdersUser();
}

OrdersMapper.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">

<!--实现延迟加载,拆分SQL语句-->
<mapper namespace="com.ahu.mapper.OrdersMapper">
    <!--
    一对一查询,基准是订单表
    resultMap中写了返回类型,这里没必要写resultType了
    -->
    <select id="queryOrdersUser" resultMap="queryOrdersUserResultMap">
        select u.id uid,u.username,u.sex,u.birthday,u.address,o.id,o.user_id,o.number,o.
        createtime,o.note
        from orders o left outer join user u on u.id = o.user_id;
    </select>

    <!--手动配置映射,查出来的数据表的列和pojo属性相对应,对应返回类型或者返回函数的泛型-->
    <resultMap id="queryOrdersUserResultMap" type="Orders">
        <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"/>

        <!--
        配置一对一?
        配置user属性的值
        association配置对应关系
        property 属性: 和orders对象的哪个属性关联
        javaType 属性: 属性数据类型 可以小写?无所谓大小写
        -->
        <association property="user" javaType="User">
            <id column="uid" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
</mapper>

主配置文件SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--约束文件,位置在mybatis的jar包-->
<configuration>
    <settings>
        <!-- 开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true" />
        <!-- 关闭立即加载-->
        <setting name="aggressiveLazyLoading" value="false" />
        <!-- 设定tostring等方法延迟加载-->
        <setting name="lazyLoadTriggerMethods" value="true" />
    </settings>


    <!--    别名配置-->
    <typeAliases>
<!--        配置别名,数据类型是pojo对象,简化为user-->
<!--        <typeAlias type="com.ahu.pojo.User" alias="user"></typeAlias>-->

<!--        定义别名也可以使用包扫描,在xml文件中直接使用类名小写即可-->
        <package name="com.ahu.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <!--
                 transactionManager 事务管理配置
                 type="JDBC"  使用的是最原始的JDBC的事务处理机制
                 type="MANAGERED" 不管理事务
            -->
            <transactionManager type="JDBC" />
            <!--
                dataSource 配置数据源,连接池
                type="POOLED" 使用连接池
                MyBatis自带连接池  (type=""UNPOOLED)
            -->
            <dataSource type="POOLED">
<!--                使用自带的数据库连接池-->
                <!--配置的是,数据库连接四大信息-->
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://127.0.0.1:3305/mybatis?characterEncoding=utf8" />
                <property name="username" value="root" />
                <property name="password" value="ahulml005" />
            </dataSource>
        </environment>
    </environments>

    <!--
      配置的是映射关系  ORM Java对象和数据表
    -->
    <mappers>
        <!--
        配置文件不在同一个文件下,填写地址应该注意
        -->
<!--        <mapper resource="com/ahu/mapper/UserMapper.xml" />-->

        <!--
        可以使用自动扫描配置,自动扫描xml文件
        一个数据表对应一个xml

        mapper标签的属性 resource="xml路径"
        package标签的属性 name="包名"

        -->
        <package name="com.ahu.mapper"/>

    </mappers>
</configuration>    

业务代码

package com.ahu.test;

import com.ahu.mapper.OrdersMapper;
import com.ahu.pojo.Orders;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MainTest {
    
    
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void before() throws IOException {
    
    
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
    }

    /**
     * SQ查询了用户和订单信息,但是运行时期只需要订单数据
     * 没有用户数据,对用户数据的查询就是浪费资源
     * 延迟查询:需要的时候就查,不需要就不查
     *
     * 方法:拆分
     * SQL语句
     */
    @Test
    public void testQueryOrdersUser(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<Orders> orders = ordersMapper.queryOrdersUser();
        for (Orders order : orders) {
    
    
            System.out.println(order);
        }
        sqlSession.close();
    }
}

一对一延迟查询

修改OrdersMapper.xml配置

 * SQ查询了用户和订单信息,但是运行时期只需要订单数据
 * 没有用户数据,对用户数据的查询就是浪费资源
 * 延迟查询:需要的时候就查,不需要就不查
 * 方法:拆分SQL语句
<?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">

<!--实现延迟加载,拆分SQL语句-->
<mapper namespace="com.ahu.mapper.OrdersMapper">
    <!--
    一对一查询,基准是订单表
    resultMap中写了返回类型,这里没必要写resultType了

    拆分sql
    select u.id uid,u.username,u.sex,u.birthday,u.address,o.id,o.user_id,o.number,o.
        createtime,o.note
        from orders o left outer join user u on u.id = o.user_id;
    -->
    <select id="queryOrdersUser" resultMap="queryOrdersUserResultMap">
        select o.id,o.user_id,o.number,o.createtime,o.note
        from orders o;
    </select>

    <!--手动配置映射,查出来的数据表的列和pojo属性相对应,对应返回类型或者返回函数的泛型-->
    <resultMap id="queryOrdersUserResultMap" type="Orders">
        <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"/>

        <!--
        配置一对一?
        配置user属性的值
        association配置对应关系
        property 属性: 和orders对象的哪个属性关联
        javaType 属性: 属性数据类型 可以小写?无所谓大小写
        column:使用哪个列作为条件进行二次查询
        select:封装的第二次查询的SQL语句
        -->
        <!--因为单独查询,所以有没必要映射-->
        <!--foreach标签的应用场景是函数传进来的参数-->
        <association property="user" javaType="User" column="user_id" select="queryUserByUserId">
<!--            <id column="uid" property="id"/>-->
<!--            <result column="username" property="username"/>-->
<!--            <result column="sex" property="sex"/>-->
<!--            <result column="birthday" property="birthday"/>-->
<!--            <result column="address" property="address"/>-->
        </association>

    </resultMap>

    <select id="queryUserByUserId" parameterType="Integer" resultType="User">
        select u.id,u.username,u.sex,u.birthday,u.address
        from user u where u.id = #{id}
    </select>
</mapper>

分情况查询

不查询uesr信息时

    @Test
    public void testQueryOrdersUser(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<Orders> orders = ordersMapper.queryOrdersUser();
        for (Orders order : orders) {
    
    
//            System.out.println(order);
            System.out.println(order.getId() + "::" + order.getUserId()
                    + "::" + order.getNumber());
        }
        sqlSession.close();
    }

查询user信息时

    @Test
    public void testQueryOrdersUser(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<Orders> orders = ordersMapper.queryOrdersUser();
        for (Orders order : orders) {
    
    
//            System.out.println(order);
            System.out.println(order.getId() + "::" + order.getUserId()
                    + "::" + order.getNumber() + "::" + order.getUser());
        }
        sqlSession.close();
    }

一对多查询

原Mybatis查询

  • 用户和订单之间是一对多的关系
  • 只输出用户信息的情况会造成浪费资源

pojo

同一对一的User和Order

配置文件

UserMapper.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 namespace="com.ahu.mapper.UserMapper">
        <select id="queryUser" resultType="user">
                select <include refid="userColumn"/> from user
        </select>

        <!--
        多条件查询
        标签where拼接查询的条件(自动检查,不需要加1=1,Mys)
        根据pojo中的对象决定查询的条件(username和sex)

        标签if对pojo的属性进行判断
        属性test判断属性是否为空


        -->
        <!--
        直接用属性名就可以如username,如果使用user.username则user是内置的属性对象,空串用''表示
        SQL语句会自动加where,也会自动删除第一个and
        -->
        <select id="queryByWhere" resultType="user" parameterType="user">
                select * from user
                <where>
                        <if test="username != null and username != ''">
                        and username like #{username}
                        </if>

                        <if test="sex != null and sex != ''">
                        and sex = #{sex}
                        </if>
                </where>
        </select>

        <!--
        批量删除
        参数是集合
        使用迭代标签foreach,标签属性parameterType,参数的数据类型,写的是集合的泛型
        迭代标签 foreach  遍历集合,固定的集合list

        属性: collection 遍历容器集合
        属性: open SQL开始的符号
        属性: close SQL结束符号
        属性: separator SQL语句参数分隔符
        属性  item 遍历的容器的元素
        -->
        <delete id="deleteUserByList" parameterType="list">
            delete from user where id in
            <foreach collection="list" open="(" close=")" separator="," item="id">
            #{id}
--             取出集合元素
            </foreach>
        </delete>

        <!--
        传入数组
        collection属性填array
        -->
        <delete id="deleteUserByArray" parameterType="int[]">
            delete from user where id in
            <foreach collection="array" open="(" close=")" separator="," item="id">
                #{id}
            </foreach>
        </delete>


        <select id="queryUserOrders" resultMap="queryUserOrdersResultMap">
            select u.id uid,u.username,u.sex,u.birthday,u.address,o.id,o.user_id,o.number,o.createtime,o.note
            from user u left outer join orders o on u.id = o.user_id;
            
        </select>

        <!--        type返回类型-->
        <resultMap id="queryUserOrdersResultMap" type="User">
            <id column="uid" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>

            <!--
            配置user对象的属性,不是单一的对象,是集合容器
            collection配置一对多
            属性property配置pojo对象的属性
            属性ofTyte指定集合泛型
            -->
            <collection property="ordersList" ofType="Orders">
                <id column="id" property="id"/>
                <id column="user_id" property="userId"/>
                <id column="number" property="number"/>
                <id column="createtime" property="createtime"/>
                <id column="note" property="note"/>
            </collection>
        </resultMap>


        <sql id="userColumn">
        id,username,sex,birthday,address
        </sql>
</mapper>

业务代码

package com.ahu.test;

import com.ahu.mapper.OrdersMapper;
import com.ahu.mapper.UserMapper;
import com.ahu.pojo.Orders;
import com.ahu.pojo.User;
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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MainTest {
    
    
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void before() throws IOException {
    
    
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
    }

    /**
     * SQ查询了用户和订单信息,但是运行时期只需要订单数据
     * 没有用户数据,对用户数据的查询就是浪费资源
     * 延迟查询:需要的时候就查,不需要就不查
     *
     * 方法:拆分SQL语句
     */
    @Test
    public void testQueryOrdersUser(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrdersMapper ordersMapper = sqlSession.getMapper(OrdersMapper.class);
        List<Orders> orders = ordersMapper.queryOrdersUser();
        for (Orders order : orders) {
    
    
//            System.out.println(order);
            System.out.println(order.getId() + "::" + order.getUserId()
                    + "::" + order.getNumber());
        }
        sqlSession.close();
    }

    /**
     * 一对多查询,以用户表为基准,不过和上例相同,Orders内置为User属性,查询出来Orders的属性user为空,不能套娃
     */
    @Test
    public void testQueryUserOrders(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.queryUserOrders();
        for (User user : users) {
    
    
            System.out.println(user);
        }
        sqlSession.close();
    }
}

多对多延迟查询

修改UserMapper.xml的配置(最下方一对多的配置)

 可以传入重命名的列名uid(防止重名)
 使用子标签select的第二次子查询也是可以使用映射的
 ofType传入泛型
<?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 namespace="com.ahu.mapper.UserMapper">
        <select id="queryUser" resultType="user">
                select <include refid="userColumn"/> from user
        </select>

        <!--
        多条件查询
        标签where拼接查询的条件(自动检查,不需要加1=1,Mys)
        根据pojo中的对象决定查询的条件(username和sex)

        标签if对pojo的属性进行判断
        属性test判断属性是否为空


        -->
        <!--
        直接用属性名就可以如username,如果使用user.username则user是内置的属性对象,空串用''表示
        SQL语句会自动加where,也会自动删除第一个and
        -->
        <select id="queryByWhere" resultType="user" parameterType="user">
                select * from user
                <where>
                        <if test="username != null and username != ''">
                        and username like #{username}
                        </if>

                        <if test="sex != null and sex != ''">
                        and sex = #{sex}
                        </if>
                </where>
        </select>

        <!--
        批量删除
        参数是集合
        使用迭代标签foreach,标签属性parameterType,参数的数据类型,写的是集合的泛型
        迭代标签 foreach  遍历集合,固定的集合list

        属性: collection 遍历容器集合
        属性: open SQL开始的符号
        属性: close SQL结束符号
        属性: separator SQL语句参数分隔符
        属性  item 遍历的容器的元素
        -->
        <delete id="deleteUserByList" parameterType="list">
            delete from user where id in
            <foreach collection="list" open="(" close=")" separator="," item="id">
            #{id}
--             取出集合元素
            </foreach>
        </delete>

        <!--
        传入数组
        collection属性填array
        -->
        <delete id="deleteUserByArray" parameterType="int[]">
            delete from user where id in
            <foreach collection="array" open="(" close=")" separator="," item="id">
                #{id}
            </foreach>
        </delete>


        <!--
        拆分sql语句
        select u.id uid,u.username,u.sex,u.birthday,u.address,o.id,o.user_id,o.number,o.createtime,o.note
            from user u left outer join orders o on u.id = o.user_id;
        -->
        <select id="queryUserOrders" resultMap="queryUserOrdersResultMap">
            select u.id uid,u.username,u.sex,u.birthday,u.address
            from user u;
            
        </select>

        <!--        type返回类型-->
        <resultMap id="queryUserOrdersResultMap" type="User">
            <id column="uid" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>

            <!--
            配置user对象的属性,不是单一的对象,是集合容器
            collection配置一对多
            属性property配置pojo对象的属性
            属性ofTyte指定集合泛型
            -->
            
            <!--            
            可以传入重命名的列名uid(防止重名)
            使用子标签select的第二次子查询也是可以使用映射的
            ofType传入泛型
            -->
            <collection property="ordersList" ofType="Orders" column="uid" select="queryOrdersByUserId">
                <id column="id" property="id"/>
                <id column="user_id" property="userId"/>
                <id column="number" property="number"/>
                <id column="createtime" property="createtime"/>
                <id column="note" property="note"/>
            </collection>
        </resultMap>

        <select id="queryOrdersByUserId" parameterType="Integer" resultType="Orders">
            select o.id,o.user_id,o.number,o.createtime,o.note
            from orders o where o.user_id = #{id};
        </select>


        <sql id="userColumn">
        id,username,sex,birthday,address
        </sql>
</mapper>

业务代码

不查询订单信息就不会出现

    /**
     * 一对多查询,以用户表为基准,不过和上例相同,Orders内置为User属性,查询出来Orders的属性user为空,不能套娃
     */
    @Test
    public void testQueryUserOrders(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.queryUserOrders();
        for (User user : users) {
    
    
            System.out.println(user.getUsername());
        }
        sqlSession.close();
    }

在这里插入图片描述

查询了订单信息就会调用

    /**
     * 一对多查询,以用户表为基准,不过和上例相同,Orders内置为User属性,查询出来Orders的属性user为空,不能套娃
     */
    @Test
    public void testQueryUserOrders(){
    
    
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = userMapper.queryUserOrders();
        for (User user : users) {
    
    
            System.out.println(user.getUsername() + "::" + user.getOrdersList());
        }
        sqlSession.close();
    }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41904699/article/details/109058518