mybatis-flex/docs/zh/base/auto-mapping.md
2023-07-29 17:40:25 +08:00

5.6 KiB
Raw Blame History

自动映射

在 MyBatis-Flex 中,内置了非常智能的 自动映射 功能,能够使得我们在查询数据的时候,从数据结果集绑定到实体类(或者 VO、DTO等等变得极其简单易用。

数据假设

假设在我们的项目中,有如下的表结构、和实体类:

账户表tb_account

CREATE TABLE IF NOT EXISTS `tb_account`
(
    `id`        INTEGER auto_increment,
    `user_name` VARCHAR(100),
    `age`       Integer
);

图书表tb_book

CREATE TABLE IF NOT EXISTS `tb_book`
(
    `id`        INTEGER auto_increment,
    `account_id` Integer,
    `title`      VARCHAR(100),
    `content`    text
);

图书和账户的关系是多对一的关系:一个账户可以拥有多本书。

角色表tb_role

CREATE TABLE IF NOT EXISTS `tb_role`
(
    `id`        INTEGER auto_increment,
    `name`      VARCHAR(100)
);

账户和角色的 多对多 关系映射表tb_role_mapping

CREATE TABLE IF NOT EXISTS `tb_role_mapping`
(
    `account_id`        INTEGER ,
    `role_id`      INTEGER
);

基础映射

基础映射指的是,定义的实体类和表结构是一一对应的关系,例如:

@Table(value = "tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;
    private String userName;
    private int age;

    //getter setter
}

Account.java 与表 tb_account 是字段和属性是一一对应关系的。此时,我们在查询数据的时候,可以通过 AccountMapper 方法直接查询,例如:

QueryWrapper qw = new QeuryWrapper();
qw.select(ACCOUNT.ALL_COLUMNS)
    .where(ACCOUNT.ID.ge(100));

List<Account> accounts = accountMapper.selectListByQuery(qw);

或者使用如下的链式查询,都可以直接得到 List<Account> 结果:accounts

QueryChain.of(accountMapper)
    .select(ACCOUNT.ALL_COLUMNS)
    .where(ACCOUNT.ID.ge(100))
    .list();

AS 映射

假设我们在 Account.java 中多定义了一些其他属性,如下所示:

@Table(value = "tb_account")
public class Account {

    @Id(keyType = KeyType.Auto)
    private Long id;
    private String userName;
    private int age;

    //最大年龄
    private int maxAge;

    //平均年龄
    private int svgAge;

    //getter setter
}

那么,我们在查询的时候,就可以通过 as 进行映射关联,查询代码如下:

QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ALL_COLUMNS,
        max(ACCOUNT.AGE).as("maxAge"),
        avg(ACCOUNT.AGE).as("svgAge")
    ).where(ACCOUNT.ID.ge(100))
    .list();

或者:

QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ALL_COLUMNS,
        max(ACCOUNT.AGE).as("max_age"),
        avg(ACCOUNT.AGE).as("svg_age")
    ).where(ACCOUNT.ID.ge(100))
    .list();

或者使用 lambda

QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ALL_COLUMNS,
        max(ACCOUNT.AGE).as(Account::getMaxAge),
        avg(ACCOUNT.AGE).as(Account::getAvgAge)
    ).where(ACCOUNT.ID.ge(100))
    .list();

多表映射

假设我们定义了一个 BootVo.java,其中包含了图书的基本信息,也包含了图书归属的用户信息,例如:

public class BookVo {

    //图书的基本字段
    private Long id;
    private Long accountId;
    private String title;
    private String content;

    //用户表的字段
    private String userName;
    private int userAge;
}

此时,我们再进行 left join 多表查询时,代码如下:

List<BookVo> bookVos = QueryChain.of(bookMapper)
    .select(
        BOOK.ALL_COLUMNS, //图书的所有字段
        ACCOUNT.USER_NAME, //用户表的 user_name 字段
        ACCOUNT.AGE.as("userAge") //用户表的 age 字段, as "userAge"
    ).form(BOOK)
    .leftJoin(ACCONT).on(BOOK.ACCOUNT_ID.eq(ACCOUNT.ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(BookVo.java);

或者,我们也可以直接在 BookVo 中,定义 Account 对象,例如:

public class BookVo {

    //图书的基本字段
    private Long id;
    private Long accountId;
    private String title;
    private String content;

    //用户
    private Account account;
}

查询代码如下:

List<BookVo> bookVos = QueryChain.of(bookMapper)
    .select(
        BOOK.DEFAULT_COLUMNS,
        ACCOUNT.DEFAULT_COLUMNS,
     )
    .form(BOOK)
    .leftJoin(ACCONT).on(BOOK.ACCOUNT_ID.eq(ACCOUNT.ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(BookVo.java);

高级映射

在以上的表结构中,一个账户可以有多本图书,那么我们假设定义的 AccountVo.java 的结构如下:

public class AccountVO {

    private Long id;
    private String userName;
    private int age;

    //账户拥有的 图书列表
    private List<Book> books;
}
List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select() // 不传入参数等同于 SQL 的 select *
    .form(ACCONT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.java);

亦或者指定查询参数:

List<AccountVO> bookVos = QueryChain.of(accountMapper)
    .select(
        ACCOUNT.ID,
        ACCOUNT.USER_NAME,
        ACCOUNT.AGE,
        BOOK.TITLE,
        BOOK.CONTENT,
     )
    .form(ACCONT)
    .leftJoin(BOOK).on(ACCOUNT.ID.eq(BOOK.ACCOUNT_ID))
    .where(ACCOUNT.ID.ge(100))
    .listAs(AccountVO.java);

高级映射的场景中,我们还可以通过注解 @RelationManyToOne 进行查询, 详情请点击 这里