您现在的位置是:首页 > 文章详情

MyBatis-Flex v1.4.7 发布,新增 4 个关联查询注解

日期:2023-07-07点击:615

MyBatis-Flex: 一个优雅的 MyBatis 增强框架

特征

1、很轻量

MyBatis-Flex 整个框架只依赖 MyBatis,再无其他任何第三方依赖。

2、只增强

MyBatis-Flex 支持 CRUD、分页查询、多表查询、批量操作,但不丢失 MyBatis 原有的任何功能。

3、高性能

MyBatis-Flex 采用独特的技术架构、相比同类框架(比如 MyBatis-Plus),MyBatis-Flex 的在增删改查等方面的性能均超越其 5~10 倍或以上。

4、更灵动

MyBatis-Flex 支持多主键、多表查询、逻辑删除、乐观锁、数据脱敏、数据加密、多数据源、分库分表、字段权限、 字段加密、多租户、事务管理、SQL 审计... 等等等等。 这一切,免费且灵动。

 

MyBatis-Flex v1.4.7 主要是新增了 4 个关联查询注解,他们分别是:

  • RelationOneToOne:用于一对一的场景
  • RelationOneToMany:用于一对多的场景
  • RelationManyToOne:用于多对一的场景
  • RelationManyToMany:用于多对多的场景

一对一 @RelationOneToOne

假设有一个账户,账户有身份证,账户和身份证的关系是一对一的关系,代码如下所示:

Account.java :

java
 public class Account implements Serializable {  @Id(keyType = KeyType.Auto)  private Long id;  private String userName;  @RelationOneToOne(selfField = "id", targetField = "accountId")  private IDCard idCard;    //getter setter }

IDCard.java :

java
 @Table(value = "tb_idcard") public class IDCard implements Serializable {  private Long accountId;  private String cardNo;  private String content;    //getter setter }

@RelationOneToOne 配置描述:

  • selfField 当前实体类的属性
  • targetField 目标对象的关系实体类的属性

PS: 若 selfField 是主键,且当前表只有 1 个主键时,可以不填写。

假设数据库 5 条 Account 数据,然后进行查询:

java
 List<Account> accounts = accountMapper.selectAllWithRelations(); System.out.println(accounts);

其执行的 SQL 如下:

sql
 SELECT `id`, `user_name`, `age` FROM `tb_account` SELECT `account_id`, `card_no`, `content` FROM `tb_idcard`  WHERE account_id IN (1, 2, 3, 4, 5)

查询打印的结果如下:

txt
 [  Account{id=1, userName='孙悟空', age=18, idCard=IDCard{accountId=1, cardNo='0001', content='内容1'}},   Account{id=2, userName='猪八戒', age=19, idCard=IDCard{accountId=2, cardNo='0002', content='内容2'}},   Account{id=3, userName='沙和尚', age=19, idCard=IDCard{accountId=3, cardNo='0003', content='内容3'}},   Account{id=4, userName='六耳猕猴', age=19, idCard=IDCard{accountId=4, cardNo='0004', content='内容4'}},   Account{id=5, userName='王麻子叔叔', age=19, idCard=IDCard{accountId=5, cardNo='0005', content='内容5'}}  ]

一对多 @RelationOneToMany

假设一个账户有很多本书籍,一本书只能归属一个账户所有;账户和书籍的关系是一对多的关系,代码如下:

Account.java :

java
 public class Account implements Serializable {  @Id(keyType = KeyType.Auto)  private Long id;  private String userName;  @RelationOneToMany(selfField = "id", targetField = "accountId")  private List<Book> books;    //getter setter }

Book.java :

java
 @Table(value = "tb_book") public class Book implements Serializable {  @Id(keyType = KeyType.Auto)  private Long id;  private Long accountId;  private String title;    //getter setter }

@RelationOneToMany 配置描述:

  • selfField 当前实体类的属性
  • targetField 目标对象的关系实体类的属性

PS: 若 selfField 是主键,且当前表只有 1 个主键时,可以不填写。

假设数据库 5 条 Account 数据,然后进行查询:

java
 List<Account> accounts = accountMapper.selectAllWithRelations(); System.out.println(accounts);

其执行的 SQL 如下:

sql
 SELECT `id`, `user_name`, `age` FROM `tb_account` SELECT `id`, `account_id`, `title`, `content` FROM `tb_book`  WHERE account_id IN (1, 2, 3, 4, 5)

多对一 @RelationManyToOne

假设一个账户有很多本书籍,一本书只能归属一个账户所有;账户和书籍的关系是一对多的关系,书籍和账户的关系为多对一的关系,代码如下:

Account.java 一对多的配置:

java
 public class Account implements Serializable {  @Id(keyType = KeyType.Auto)  private Long id;  private String userName;  @RelationOneToMany(selfField = "id", targetField = "accountId")  private List<Book> books;    //getter setter }

Book.java 多对一的配置:

java
 @Table(value = "tb_book") public class Book implements Serializable {  @Id(keyType = KeyType.Auto)  private Long id;  private Long accountId;  private String title;    @RelationManyToOne(selfField = "accountId", targetField = "id")  private Account account;    //getter setter }

@RelationManyToOne 配置描述:

  • selfField 当前实体类的属性
  • targetField 目标对象的关系实体类的属性

PS: 若 targetField 目标对象的是主键,且目标对象的表只有 1 个主键时,可以不填写。

多对多 @RelationManyToOne

假设一个账户可以有多个角色,一个角色也可以有多个账户,他们是多对多的关系,需要通过中间件表 tb_role_mapping 来维护:

tb_role_mapping 的表结构如下:

sql
 CREATE TABLE `tb_role_mapping` (  `account_id` INTEGER ,  `role_id` INTEGER );

Account.java 多对多的配置:

java
 public class Account implements Serializable {  @Id(keyType = KeyType.Auto)  private Long id;  private String userName;  @RelationManyToMany(  joinTable = "tb_role_mapping", // 中间表  selfField = "id", joinSelfColumn = "account_id",  targetField = "id", joinTargetColumn = "role_id"  )  private List<Role> roles;    //getter setter }

Role.java 多对多的配置:

java
 @Table(value = "tb_role") public class Role implements Serializable {  private Long id;  private String name;  @RelationManyToMany(  joinTable = "tb_role_mapping",  selfField = "id", joinSelfColumn = "role_id",  targetField = "id", joinTargetColumn = "account_id"  )  private List<Account> accounts;    //getter setter }

@RelationManyToMany 配置描述:

  • selfField 当前实体类的属性
  • targetField 目标对象的关系实体类的属性
  • joinTable 中间表
  • joinSelfColumn 当前表和中间表的关系字段
  • joinTargetColumn 目标表和中间表的关系字段

注意:selfField 和 targetField 配置的是类的属性名,joinSelfColumn 和 joinTargetColumn 配置的是中间表的字段名。

 selfField  targetField 分别是两张关系表的主键,且表只有 1 个主键时,可以不填写。

父子关系查询

比如在一些系统中,比如菜单会有一些父子关系,例如菜单表如下:

sql
 CREATE TABLE `tb_menu` (  `id` INTEGER auto_increment,  `parent_id` INTEGER,   `name` VARCHAR(100) );

Menu.java 定义如下:

java
 @Table(value = "tb_menu") public class Menu implements Serializable {  private Long id;  private Long parentId;  private String name;  @RelationManyToOne(selfField = "parentId", targetField = "id")  private Menu parent;  @RelationOneToMany(selfField = "id", targetField = "parentId")  private List<Menu> children;  //getter setter }

查询顶级菜单:

java
 QueryWrapper qw = QueryWrapper.create(); qw.where(MENU.PARENT_ID.eq(0)); List<Menu> menus = menuMapper.selectListWithRelationsByQuery(qw); System.out.println(JSON.toJSONString(menus));

SQL 执行如下:

sql
 SELECT `id`, `parent_id`, `name` FROM `tb_menu` WHERE `parent_id` = 0 SELECT `id`, `parent_id`, `name` FROM `tb_menu` WHERE id = 0 SELECT `id`, `parent_id`, `name` FROM `tb_menu` WHERE parent_id IN (1, 2, 3)

JSON 输出内容如下:

json
 [  {  "children": [  {  "id": 4,  "name": "子菜单",  "parentId": 1  },  {  "id": 5,  "name": "子菜单",  "parentId": 1  }  ],  "id": 1,  "name": "顶级菜单1",  "parentId": 0  },  {  "children": [],  "id": 2,  "name": "顶级菜单2",  "parentId": 0  },  {  "children": [  {  "id": 6,  "name": "子菜单",  "parentId": 3  },  {  "id": 7,  "name": "子菜单",  "parentId": 3  },  {  "id": 8,  "name": "子菜单",  "parentId": 3  }  ],  "id": 3,  "name": "顶级菜单3",  "parentId": 0  } ] 

MyBatis-Flex v1.4.7 更新如下:

  • 新增:@RelationManyToMany @RelationManyToOne @RelationOneToMany @RelationOneToOne 4 个注解用于关联查询
  • 新增:为 QueryMethods 添加更多的 SQL 函数重载,感谢 @王帅
  • 新增:代码生成器添加 @Mapper 主键的启用配置,感谢 @王帅
  • 新增:BaseMapper 添加 selectRowsByQuery() 方法
  • 优化:重构 selectCountByQuery 方法,移除不必要的实现类,感谢 @王帅
  • 优化:重构 TableInfo.buildResultMap(),防止在某些极端情况出现赋值错误的问题
  • 修复:代码生成器 ControllerGenerator 的 OverwriteEnable 配置不生效的问题
  • 文档:添加关于 QueryMethods 的一些用法和示例,感谢 @王帅
  • 文档:修改 apt 配置错误的问题,感谢 @王帅
  • 文档:添加关于 sql 函数的一些函数说明
  • 文档:添加关于关联查询注解的相关文档

 

进一步了解 MyBatis-Flex 框架,请参考一下链接:

 

和其他框架对比请参考:

原文链接:https://www.oschina.net/news/248338/mybatis-flex-1-4-7-released
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章