# 连表查询

通过对dao(mapper)层注解的方式来进行一对一,一对多的连表查询,极大的提高了开发效率。

说明:

  • @Link注解方式,不会影响到Mybatis自带的注解,以及在Mybatis的Xml中编写Sql语句。
  • 一对多的连表查询,会有N+1的问题。

# 前提条件准备

为了直观感受和使用连表查询,下面将通过4张表(t_teat_at_test_bt_test_ct_test_d)进行说明,四张表分别用abcd进行简称。 以下连表查询都是写在TestADao.class类中


类:TestADao.class

public interface TestADao extends BaseDao<TestAVo, TestADto> {
    ........
}

类:TestADto.class

@Data
public class TestADto implements Serializable {
    private static final long serialVersionUID = 1L;

    protected TestAVo testAVo2;
    protected TestAVo testAVo;
    protected TestBVo testBVo;
    protected TestCVo testCVo;
    protected TestDVo testDVo;
    protected List<TestBDto> testBList;
    protected List<TestCDto> testCList;
    
    protected Integer count;
    protected String crtBy;
}

# 演示表结构

表:t_test_a

字段 类型 描述
id bigint 主键
b_id bigint b表主键
c_id bigint c表主键
a_id bigint a表主键

表:t_test_b

字段 类型 描述
id bigint 主键
a_id bigint a表主键
c_id bigint c表主键

表:t_test_c

字段 类型 描述
id bigint 主键
a_id bigint a表主键
b_id bigint b表主键

表:t_test_d

字段 类型 描述
id bigint 主键
a_id bigint a表主键

# 一对一连表查询

说明:

  • 一对一连表查询,可以进行左连接,右连接,内连接查询,且可以进行多表(大于等于2张表)连查。
  • 左连接或者右连接查询时,可以在ON或者WHERE后区别进行条件过滤。

# a 内连 a

@Link(ones = { 
    @OneToOne(leftColumn = "a_id", rightClass = TestAVo.class, rightAlias = "testAVo2") })
List<TestADto> listTestAATestA(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

说明:

  • 由于查询的两个表为同一个表,所以必须给其中一个表设置别名,且该别名必须跟TestADto对象中得属性名对应,如:rightAlias = "testAVo2"。
  • 由于在TestADao.class中进行注解,所有leftClass默认为TestAVo.class,可以默认省略。
  • leftColumn或者rightColumn都不写,默认为表主键。
  • leftAlias或者rightAlias都不写,默认都为表实体对象属性值,如:leftAlias = "testAVo"。

# a 内连 c

@Link(ones = { @OneToOne(leftColumn = "c_id", rightClass = TestCVo.class) })
List<TestADto> listTestAATestC(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

说明:

  • a表的c_id字段,与c表中的id主键字段,进行连表查询。

# a 内连 b

@Link(ones = { @OneToOne(rightClass = TestBVo.class, rightColumn = "a_id") })
List<TestADto> listTestAATestB(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

说明:

  • a表的id主键字段,与b表中的a_id字段,进行连表查询。

# a 内连 b, a 内连 c

@Link(ones = { @OneToOne(leftColumn = "b_id", rightClass = TestBVo.class),
               @OneToOne(leftColumn = "c_id", rightClass = TestCVo.class)})
List<TestADto> listTestAATestBATestC(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 内连 b, b 内连 c, a 内连 d

@Link( ones = { 
    @OneToOne(leftColumn = "b_id", rightClass = TestBVo.class),
    @OneToOne(leftClass = TestBVo.class, leftColumn = "c_id", rightClass = TestCVo.class),
    @OneToOne(rightClass = TestDVo.class, rightColumn = "a_id")})
List<TestADto> listTestAATestBATestCATestD(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 左连 b

@Link( ones = { 
    @OneToOne(leftColumn = "b_id", rightClass = TestBVo.class, 
        joinType = JoinType.LEFT, onArgName = "abOn") })
List<TestADto> listTestALtTestB(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

说明:

  • JoinType.LEFT表示左连接。
  • onArgName = "abOn"表示左连接ON后面的条件参数,通过abOn可以在ON后面进行条件过滤。

# a 左连 ba 左连 c

@Link( ones = { 
    @OneToOne(leftColumn = "b_id", rightClass = TestBVo.class, 
        joinType = JoinType.LEFT, onArgName = "abOn"), 
    @OneToOne(leftColumn = "c_id", rightClass = TestCVo.class, 
        joinType = JoinType.LEFT, onArgName = "acOn")})
List<TestADto> listTestALtTestBLtTestC(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 右连 b

@Link( ones = { 
    @OneToOne(leftColumn = "b_id", rightClass = TestCVo.class, 
        joinType = JoinType.RIGHT, onArgName = "acOn") })
List<TestADto> listTestARtTestC(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 内连 b 分页查询

@Link( ones = { 
    @OneToOne(rightClass = TestBVo.class, rightColumn = "a_id") })
IPage<TestADto> pageTestAATestB(IPage<TestADto> page, @Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 内连 b 条数查询

@Link( ones = { @OneToOne(rightClass = TestBVo.class, rightColumn = "a_id") })
Integer countTestAATestB(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# 一对多连表查询

说明:

  • 一对多连表查询,可以先进行一对一查询,再进行一对多查询。
  • 一对多查询,多的那部分还可以进行一对一查询。

# a 一对多 b

@Link( manys = { 
    @OneToMany(leftColumn = "b_id", rightClass = TestBVo.class, 
        ofTypeClass = TestBDto.class, property = "testBList") })
List<TestADto> listTestAWTestB(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

说明:

  • ofTypeClass需要配置多表实体对应的Dto类。
  • rightClass可以省略,会根据 ofTypeClass实体对象类进行规制解析。
  • property对应TestADto中类型为List<TestBDto>的属性名,即testBList。

# a 一对多 ba 一对多 c

@Link( manys = { 
    @OneToMany(leftColumn = "b_id", rightClass = TestBVo.class, 
        ofTypeClass = TestBDto.class, property = "testBList"),
    @OneToMany(leftColumn = "c_id", rightClass = TestCVo.class, 
        ofTypeClass = TestCDto.class, property = "testCList")})
List<TestADto> listTestAWTestBWTestC(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 内连 ba 一对多 b

@Link( ones = { @OneToOne(leftColumn = "b_id", rightClass = TestBVo.class)},
    manys = { @OneToMany(leftClass = TestAVo.class, leftColumn = "b_id", 
        rightClass = TestBVo.class, ofTypeClass = TestBDto.class, property = "testBList") })
List<TestADto> listTestAATestBWTestB(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

# a 内连 b,(a 一对多 bb 内连 c)

@Link( ones = { @OneToOne(leftColumn = "b_id", rightClass = TestBVo.class)},
    manys = { @OneToMany(leftClass = TestAVo.class, leftColumn = "b_id", 
        rightClass = TestBVo.class, ofTypeClass = TestBDto.class, property = "testBList", 
        ones = { @OneToOne(leftColumn = "c_id", rightClass = TestCVo.class)} )})
List<TestADto> listTestAATestBWTestBATestC(@Param(Constants.WRAPPER) Wrapper<TestAVo> wrapper);

说明:

  • OneToMany中有 OneToOne[]类型的属性。
赞助商