Java52Mybatis:高级查询,注解开发

Posted 码农编程录

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java52Mybatis:高级查询,注解开发相关的知识,希望对你有一定的参考价值。


1.OrderMapper.xml:用u,订o,详d,商i

用户和订单:一对多。订单和商品:多对多
在这里插入图片描述
在这里插入图片描述

<?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="com.itheima.mapper.OrderMapper">  
     <!--多表关联查询:1.多表关联情况下的实体设计。 2.多表关联的sql语句。-->                
     <!--多表查询 包含 订单表信息 和 用户表信息-->
    <select id="findOrderAndUserByOrderNumber" resultMap="oneToOne">
      select *,u.id uid,o.id oid from tb_user u,tb_order o
          where u.id  = o.user_id
            and o.order_number=#{orderNumber}
    </select>

    <!-- 定义一对一的结果集映射。单表autoMapping自动开启,嵌套结果集要手动开启 -->
    <resultMap id="oneToOne" type="Order" autoMapping="true">
        <id column="oid" property="id"></id>
        <!-- association一对一的配置
                property: 一方的属性即Order的user属性。javaType指定属性类型。
        -->
        <association property="user" javaType="User" autoMapping="true" >
            <id column="uid" property="id"></id>
        </association>
    </resultMap>

<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
    <select id="findOrderAndUserAndOrderDetailsByOrderNumber" resultMap="oneToMany">
        select *,u.id uid,o.id oid,d.id did
          from  tb_user u,
                tb_order o,
                tb_orderdetail d
            where u.id = o.user_id
            and o.id = d.order_id
            and o.order_number=#{orderNumber}
    </select>

    <resultMap id="oneToMany" type="Order" autoMapping="true" extends="oneToOne">
      <!--  <id column="oid" property="id"></id>    
        <association property="user" javaType="User" autoMapping="true">
            <id column="uid" property="id"></id>
        </association>-->     <!--用了继承,所以注释-->
        <!-- collection一对多映射
                property: 多方的属性名
                javaType:属性的类型
                ofType: 集合的泛型
         -->
        <collection property="orderdetailList" javaType="List" ofType="OrderDetail" autoMapping="true">
            <id column="did" property="id"></id>
        </collection>
    </resultMap>

<!--1111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
    <select id="findOrderAndUserAndOrderDetailsAndItemByOrderNumber" resultMap="manyToMany">
        select *,u.id uid,o.id oid,d.id did,i.id iid
            from tb_user u,
                     tb_order o,
                     tb_orderdetail d,
                     tb_item i
            where
			      u.id = o.user_id
              and  o.id = d.order_id
              and d.item_id = i.id
              and o.order_number = #{orderNumber}
    </select>
    
    <!--
        多对多查询的本质: 还是一对多的配置,借助中间表实现一对多的关系。
     -->
    <resultMap id="manyToMany" type="Order" extends="oneToOne" autoMapping="true">
        <collection property="orderdetailList" javaType="List" ofType="OrderDetail" autoMapping="true">
            <id column="did" property="id"></id>
            <association property="item" javaType="Item" autoMapping="true">
                <id column="iid" property="id"></id>
            </association>
        </collection>
    </resultMap>

<!--111111111111111111111111111111111111111111111111111111111111111111111111111111111-->
    <select id="findOrderLazyUser" resultMap="lazyUser">
        select * from tb_order where order_number = #{orderNumber}
    </select>

    <resultMap id="lazyUser" type="Order" autoMapping="true">
        <id property="id" column="id"></id>
        <!-- 延迟加载
                select : 配置需要执行的sql语句
                column: sql语句执行时需要的参数所在的列,即上一条sql执行某一列值
         -->
        <association property="user" javaType="User" column="user_id" select="com.itheima.mapper.UserMapper.findUserById" autoMapping="true">
            <id column="id" property="id"></id>  <!--findUserById在【Java48】中UserMapper.xml已写,返回user-->
        </association>
    </resultMap>
</mapper>

如下order_number和user_id等满足驼峰映射(mybatis-config.xml已开启),自动映射不要配了。如下将uid映射到user对象id属性,oid映射到order对象的id属性。
在这里插入图片描述
没有多表查询如下,懒/延时加载用两条sql,分开才有先后顺序。
在这里插入图片描述
在这里插入图片描述

2.domain

package com.itheima.domain;
import java.util.List;

public class Order { //订单表
    private Integer id;
    private Long userId;
    private String orderNumber;
    
    private User user;  //多变关联情况下实体的设计:可以考虑,将关联的表对应的实体类型作为当前的属性。
    private List<Orderdetail> orderdetailList; //订单携带详情,详情里再携带商品

    public List<Orderdetail> getOrderdetailList() {
        return orderdetailList;
    }
    public void setOrderdetailList(List<Orderdetail> orderdetailList) {
        this.orderdetailList = orderdetailList;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public String getOrderNumber() {
        return orderNumber;
    }
    public void setOrderNumber(String orderNumber) {
        this.orderNumber = orderNumber;
    }
    @Override
    public String toString() {  //重新生成有user
        return "Order{" +
                "id=" + id +
                ", userId=" + userId +
                ", orderNumber='" + orderNumber + '\\'' +
                ", user=" + user +
                '}';
    }
}
package com.itheima.domain;

public class Orderdetail {    
    private Integer id;    
    private Double totalPrice;    
    private Integer status;
    private Item item;  //携带商品
    public Item getItem() {
        return item;
    }
    public void setItem(Item item) {
        this.item = item;
    }
    public Double getTotalPrice() {
        return totalPrice;
    }
    public void setTotalPrice(Double totalPrice) {
        this.totalPrice = totalPrice;
    }
    public Integer getStatus() {
        return status;
    }
    public void setStatus(Integer status) {
        this.status = status;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "Orderdetail{" +
                "id=" + id +
                ", totalPrice=" + totalPrice +
                ", status=" + status +
                ", item=" + item +
                '}';
    }
}

3.mapper

package com.itheima.mapper;
import com.itheima.domain.Order;
import org.apache.ibatis.annotations.Param;

public interface OrderMapper {
    //需求:通过订单编号20140921003查询出订单信息,并查询出下单人信息。
    public Order findOrderAndUserByOrderNumber(@Param("orderNumber") String orderNumber);

    //	需求:通过订单编号20140921001查询订单,并查询出下单人信息以及查询出订单详情。
    public Order findOrderAndUserAndOrderDetailsByOrderNumber(@Param("orderNumber") String orderNumber);

    //通过订单号20140921001查询订单,查询出下单人信息并且查询出订单详情以及商品数据
    public Order findOrderAndUserAndOrderDetailsAndItemByOrderNumber(@Param("orderNumber") String orderNumber);

    //延迟加载需求:通过订单编号20140921001查询order并延迟加载user信息
    public Order findOrderLazyUser(@Param("orderNumber") String orderNumber);
}

4.test

package com.itheima.mapper;
import com.itheima.domain.Order;
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.InputStream;
import static org.junit.Assert.*;

public class OrderMapperTest {
    private OrderMapper orderMapper;
    @Before
    public void setUp() throws Exception {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        orderMapper = sqlSession.getMapper(OrderMapper.class);
    }
    @Test
    public void findOrderAndUserByOrderNumber() {
        Order order = orderMapper.findOrderAndUserByOrderNumber("20140921003");
        System.out.println(order);
    }
    @Test
    public void findOrderAndUserAndOrderDetailsByOrderNumber(){
        Order order = orderMapper.findOrderAndUserAndOrderDetailsByOrderNumber("20140921001");
        System.out.println(order);
        System.out.println(order.getOrderdetailList());
    }
    @Test
    public void findOrderAndUserAndOrderDetailsAndItemByOrderNumber(){
        Order order = orderMapper.findOrderAndUserAndOrderDetailsAndItemByOrderNumber("20140921001");
        System.out.println(order);
        System.out.println(order.getOrderdetailList());
    }
    @Test
    public void findOrderLazyUser(){
        Order order = orderMapper.findOrderLazyUser("20140921001");
        System.out.println(order.getOrderNumber());
        System.out.println("开始使用用户的信息了");
        System.out.println(order.getUser().getName());
    }
}

findOrderAndUserByOrderNumber()执行结果如下。
在这里插入图片描述
findOrderAndUserAndOrderDetailsByOrderNumber()执行结果如下。
在这里插入图片描述
findOrderAndUserAndOrderDetailsAndItemByOrderNumber()执行结果如下,多个Orderdetail。
在这里插入图片描述
findOrderLazyUser执行结果如下,用的时候才去加载。
在这里插入图片描述

5.mapper

xml配置配的东西多,但是所有配置都在一起。注解虽然配的少,但分布在各个地方。
在这里插入图片描述

package com.itheima.mapper;
import com.itheima.domain.User;
import com.itheima.sql.UserSql;
import org.apache.ibatis.annotations.*;
import java.util.HashMap;
import java.util.List;

public interface UserMapper { //注解就不用xxMapper.xml映射文件了
    @Select("select * from tb_user where id = #{id}")
    public User findUserById2(@Param("id") int id);

//11111111111111111111111111111111111111111111111111111111111111111111111111111111111
    @Insert("insert into tb_user(user_name,age) values(#{userName},#{age})")
    @Options(useGeneratedKeys = true,keyProperty = "id",keyColumn = "id") //新增主键回显
    public void addUser(User user);

//11111111111111111111111111111111111111111111111111111111111111111111111111111111111
    /**
     *  Results : 注解的作用和<resultMap></resultMap>一样,声明结果集映射
     *  Result: 注解的作用和<result><result/> 标签作用一致,配置一组列和属性的映射关系的
     */
    @Results({
            @Result(column = "uid",property = "id"),
            @Result(column = "uname",property = "userName"),
            @Result(column = "uage",property = "age"),
            @Result(column = "usex",property = "sex")
    })
    @Select("select id uid,user_name uname,age uage,sex usex from tb_user where id = #{id}")
    public User findUserById3(@Param("id") int id);  //如上行自定义别名,无法自动映射,需自定义结果集映射

//1111111111111111111111111111111111111111111111111111111111111111111111111111111111111
    /**
     *  如果用户名不为空,就按照用户名查询, //动态sql注解开发,下面的第3节
     *  如果年龄大于0,就查询年龄大于指定值的用户信息
     */
    @SelectProvider(type = UserSql.class,method = "findUsersByCondition")
    public以上是关于Java52Mybatis:高级查询,注解开发的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis快速入门

mybatis入门

Mybatis框架

JavaLearn#(28)MyBatis高级:无级联查询级联查询(立即加载结果映射延迟加载)多表连接查询MyBatis注解MyBatis运行原理面试题

MyBatis总结

Java_MyBatis