JavaEE简单示例——使用注解式开发完成多表查询

  • Post author:
  • Post category:java


简单介绍:

使用多表的注解式开发和之前我们使用嵌套查询的XML配置文件的思维逻辑是一样的,只不过将对应的标签换成了属性的方式进行配置,所以我们只需要在理解了XML配置文件的基础上去对应标签和属性之间的关系就可以了。

一对一查询:

在一对一的查询的时候,使用

@One注解

表示一对一查询,类似于我们在XML注解中使用的

<association>

标签,

@Recults

类似于XML注解中的

<resultMap>

标签,

@Result

类似于我们的

<result>

标签,需要用到的注解基本就是上面这些,然后我们来看语法的基本格式:

根据我们之前的需求,通过输入的学生的id查询出该学生对应的学生卡的详细信息

//    这个接口用来配置基于注解式开发的多表查询
//    一对一查询,通过订单号查询该订单所包含的商品的详细信息
    @Select("select * from id_card where id_card = #{id}")
    public idCard selectIdCardById(int i);
    @Select("select * from student where id = #{id}")
    @Results({@Result(property = "id_card" , column = "id_card" ,
            one = @One(select="Mappers.moreTableMapper.selectIdCardById"))})
    public student selectStudentById(int i);

我们使用的是嵌套查询的方式,所以需要有两条SQL语句进行查询,最上面的是子查询,也就是根据传入的学生的id_card信息查询出该信息对应的学生卡的详细信息。下面的方法就是用来调用这条SQL语句的,方法的返回值就是idCard类。

下面的SQL语句是父查询,也就是根据输入的id查询出与id对应的学生的详细信息,其中@Select注解内的参数是SQL语句,@Results里面的内容就是配置一对一的类的属性和表中字段的映射规则,在之前的使用XML配置一对一属性中我们说过,因为在Java实体类中的id_card属性的数据类型是idCard,而在表中与之对应的这一列的数据类型是int,而真正的数据是通过这一列的数据从id_card这张表中查询出来的数据,而这些数据通过子查询语句也就是第一条语句被查询出来封装成idCard类然后返回到父查询中当作id_card属性的值,而这个过程就是通过one属性对应的值来决定的。

在一对一查询中最重要的一个属性就是one属性,这个属性就是指定查询的方式是一对一查询,并且指定了子查询的SQL语句,也就完成了给子查询传递参数和接收子查询的返回值的过程

在子查询中,我们可以看到one属性对应的是一个@One注释,而注释中的内容就是指向的子查询的位置,select的值就是子查询的位置,这个位置信息由”接口所在的包名.接口名.接口中子查询对应的方法“组成,这样通过这个属性将父查询和子查询完整的串联在一起,就构成了一条完整的嵌套查询语句。

测试类:

public void testSelectStudentById() {
        student student = mapper.selectStudentById(1);
        System.out.println(student.toString());
    }

    public void testSelectIdCardById() {
        idCard idCard = mapper.selectIdCardById(1);
        System.out.println(idCard.toString());
    }

在测试类中我们运行对应的方法,就可以得到下面的结果:

就可以得到与id为1的学生对应的学生信息和学生卡信息

一对多查询:

在一对多的查询的时候,使用

@Many注解

表示一对多查询,类似于我们在XML注解中使用的

<collection>

标签,

@Recults

类似于XML注解中的

<resultMap>

标签,

@Result

类似于我们的

<result>

标签,需要用到的注解基本就是上面这些,然后我们来看语法的基本格式:

根据之前我们学习XML配置文件的时候的需求,我们通过输入一个人的id值,得到与id值对应的这个人的多个订单信息:

//    一对多查询,通过用户的id查询属于用户的多个订单
    @Select("select * from orders where user_id = #{id}")
    public orders selectOrdersById_oneToMore(int i);
    @Select("select * from student where id = #{id}")
    @Results({@Result(property = "orders" , column = "order_id" ,
            many = @Many(select = "Mappers.moreTableMapper.selectOrdersById_oneToMore"))})
    public student selectStudentById_oneToMore(int i);

我们依然使用的是嵌套查询的方式,这种方式可以很清晰的看出SQL语句的嵌套关系,方便我们理解这些配置的作用以及参数和结果集的封装和传递。

在一对多的查询中,最重要的一个属性就使many属性,他表示我们使用的是一对多的查询,并且也将我们的父查询和子查询两条单独的SQL语句连接起来,组成一条完整的嵌套查询语句:

在注解式开发中,我们不需要设置List集合的泛型的类型,也就是没有ofTyoe属性,因为在注解式开发中,我们的MyBatis可以自动帮我们匹配子查询的返回值和我们配置的自定义规则映射中的POJO实体类中的属性的数据类型是否匹配,如果不匹配,则会直接报错。

在完成了这些配置之后,可以看到,与一对一的查询相比,只是更换了一个属性名称和一个注解名称,将one属性换成了many属性,将@One注解换成了@Many注解,其基本的逻辑和参数的传递以及结果集的封装逻辑都是不变的。

然后来到我们的测试类中测试我们写好的方法:

public void testSelectStudentById_oneToMore(){
        student student = mapper.selectStudentById_oneToMore(1);
        System.out.println(student.toString());
    }

如果我们之前的配置正确无误的话,我们运行这个方法,会得到如下的结果:

就可以得到我们输入的id的值对应的用户的信息,以及这个用户对应的多条订单的信息,这就是哦我们基本的基于注解式开发的一对多的配置。

多对多查询:

之前我们也讲过,

多对多查询的本质就是将两个对多对的表,通过一张中间表,分成了两个中间表对两个表的一对多查询。

所以在多对多查询中,我们学习的重点并不是配置文件或者是注解的编写,而是重点放在通过中间表去查询出我们想要的数据,更偏向于SQL的编写和学习。

根据我们之前学习基于XML配置文件的时候的需求,通过输入一个订单id,查询出该订单所包含的多个商品的详细信息;通过输入一个商品的编号,查询出包含该商品的多个订单的信息。

在这个过程中,订单和商品就是一个多对多的关系,一个商品对应多个订单,而一个订单又可以对应多个商品,所以这个时候,我们就使用一个中间表来维护订单和商品之间的对应关系,接下来我们就看看这三个表的结构:

订单表:

商品表:

中间表:

在这三张表里面,最重要的就是这张维护了订单和商品对应关系的中间表。order_id表示的就是订单编号,同一个订单编号就表示这是同一个订单。而good_id表示的就是商品的编号,而同一个商品编号就表示这是同一个商品。

在清楚了这三张表的对应关系之后,我们就可以进行查询操作了,在编写复杂的SQL语句的时候,我们可以先将复杂的查询分解成简单的单个查询,比如我们分析一下我们的需求:

通过输入一个订单id,查询出该订单所包含的多个商品的详细信息

就可以分解出两个简单的SQL语句:

1.首先从中间表查询出订单的id对应的商品的id:

select * from order_project where order_id = 1;

2.通过第一条SQL语句的查询结果查询出订单id对应的商品的详细信息:

select * from goods where goods_id in (select goods_id from order_project where order_id = 1);

这样,我们的SQL语句就写好了,知道了我们的SQL语句之后,我们就可以看出我们SQL语句的嵌套关系了,那么再去编写基于注释的接口文件就非常的简单了:

那么我们的最终目的是查询出订单信息,所以要给查询订单的SQL语句配置自定义映射规则,然后select属性指向的就是查询商品信息的SQL语句,只要清楚了其中的逻辑关系,无论是XML配置文件还是基于注解的开发都可以非常简单的编写出来。

然后我们在测试类中开始测试接口文件中的方法:

如果配置正确,那么最终会看到下面的结果:

那么我们最终展示一下完整的接口文件和测试类:

接口文件:

package Mapper;

import com.mybatis.POJO.goods;
import com.mybatis.POJO.idCard;
import com.mybatis.POJO.orders;
import com.mybatis.POJO.user;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface selectMoreMapper {
//    配置一对一查询
    @Select("select * from id_card where id_card = #{id}")
    public idCard selectIdCardByUserId_OneToMore(int i);
    @Select("select * from user where id = #{id}")
    @Results({@Result(property = "id_card" , column = "id_card" ,
            one = @One(select = "Mapper.selectMoreMapper.selectIdCardByUserId_OneToMore"))})
    public user selectUserById_OneToMore(int i);

//    配置一对多查询
    @Select("select * from orders where order_id = #{id}")
    public List<orders> selectOrderById_OneToMore(int i);
    @Select("select * from user where id = #{id}")
    @Results({@Result(property = "order_id" , column = "order_id" ,
            many = @Many(select = "Mapper.selectMoreMapper.selectOrderById_OneToMore")) ,
    @Result(property = "id" , column = "id") , @Result(property = "name" , column = "name") , @Result(property = "sex" , column = "sex")})
    public user selectUserById_OmeToMore(int i);

//    配置多对多查询,首先是根据订单查询中订单中的多个商品的详细信息
    @Select("select * from goods where goods_id in (select goods_id from order_project where order_id = #{id})")
    public List<goods> selectGoodsById_MoreToMore(int i);
    @Select("select * from orders where id = #{id}")
    @Results({@Result(property = "goodsList" , column = "order_id" ,
            many = @Many(select = "Mapper.selectMoreMapper.selectGoodsById_MoreToMore"))})
    public List<orders> selectOrdersById_MoreToMore(int i);

//    配置多对多查询,然后是通过商品编号查询包含此商品的订单
    @Select("select * from orders where id in (select id from order_project where goods_id = #{id})")
    public List<orders> selectOrderByGoodsId_MoreToMore(int i);
    @Select("select * from goods where goods_id = #{id}")
    @Results({@Result(property = "ordersList" , column = "goods_id" ,
            many = @Many(select = "Mapper.selectMoreMapper.selectOrderByGoodsId_MoreToMore")) ,
            @Result(property = "goods_id" , column = "goods_id"),
            @Result(property = "good_information" , column = "good_information")})
    public List<goods> selectGoodsByGoodsId_MoreToMore(int i);

}

测试类:

package Mapper;

import com.mybatis.POJO.goods;
import com.mybatis.POJO.idCard;
import com.mybatis.POJO.orders;
import com.mybatis.POJO.user;
import junit.framework.TestCase;
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 java.io.InputStream;

public class selectMoreMapperTest extends TestCase {
    SqlSession session = null;
    selectMoreMapper mapper = null;

    public void setUp() throws Exception {
        InputStream stream = Resources.getResourceAsStream("mybatis.xml");
        SqlSessionFactory build = new SqlSessionFactoryBuilder().build(stream);
        session = build.openSession(true);
        mapper = session.getMapper(selectMoreMapper.class);
    }

    public void testSelectIdCardByUserId_OneToMore() {
        idCard idCard = mapper.selectIdCardByUserId_OneToMore(1);
        System.out.println(idCard.toString());
    }

    public void testSelectUserById_OneToMore() {
        user user = mapper.selectUserById_OneToMore(1);
        System.out.println(user.toString());
    }

    public void testSelectUserById_OmeToMore(){
        user user = mapper.selectUserById_OmeToMore(1);
        System.out.println(user.toString());
    }
    public void testSelectOrderById_OneToMore(){
        for (orders orders : mapper.selectOrderById_OneToMore(1)) {
            System.out.println(orders.toString());
        }
    }

    public void testSelectOrdersById_MoreToMore(){
        for (orders orders : mapper.selectOrdersById_MoreToMore(1)) {
            System.out.println(orders.toString());
        }
    }
    public void testSelectGoodsById_MoreToMore(){
        for (goods goods : mapper.selectGoodsById_MoreToMore(1)) {
            System.out.println(goods);
        }
    }

    public void testSelectOrdersByGoodsId_MoreToMore(){
        for (orders orders : mapper.selectOrderByGoodsId_MoreToMore(1)) {
            System.out.println(orders);
        }
    }
    public void testSelectGoodsByGoodsId_MoreToMore(){
        for (goods goods : mapper.selectGoodsByGoodsId_MoreToMore(1)) {
            System.out.println(goods.toString());
        }
    }
}

注意点:

在整个的配置多表查询中,只要清楚的理解了表与表之间的联系,以及属性和表字段之间的映射关系,属性与属性之间的嵌套关系,这一章节其实非常的简单。



版权声明:本文为hssjsh原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。