1、前言
上一篇文章《Springboot集成Mybatis-flex(一)》提到Mybatis Flex和Spring Boot的初步集成和基础使用。今天我们再来探索Mybatis Flex其他特性的使用。
2、数据填充
数据填充指的是,当 Entity 数据被插入 或者 更新的时候,会为字段进行一些默认的数据设置。这个非常有用,比如当某个 entity 被插入时候 会设置一些数据插入的时间、数据插入的用户 id,多租户的场景下设置当前租户信息等等。
MyBatis-Flex 提供了两种方式,帮助开发者进行数据填充。
- 通过 @Table 注解的 onInsert 和 onUpdate配置进行操作。
- 通过 @Column 注解的 onInsertValue 和 onUpdateValue配置进行操作。
2.1、@Table的onInsert填充
@Table应用于实体类的注解,提供了onInsert填充属性,而该属性接收一个InsertListener的监听器。
/**
* 数据库表信息注解。
*
* @author Michael Yang
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Table {
/**
* 显式指定表名称。
*/
String value();
/**
* 数据库的 schema(模式)。
*/
String schema() default "";
/**
* 默认为 驼峰属性 转换为 下划线字段。
*/
boolean camelToUnderline() default true;
/**
* 默认使用哪个数据源,若系统找不到该指定的数据源时,默认使用第一个数据源。
*/
String dataSource() default "";
/**
* 监听 entity 的 insert 行为。
*/
Class<? extends InsertListener>[] onInsert() default {};
/**
* 监听 entity 的 update 行为。
*/
Class<? extends UpdateListener>[] onUpdate() default {};
/**
* 监听 entity 的查询数据的 set 行为,用户主动 set 不会触发。
*/
Class<? extends SetListener>[] onSet() default {};
/**
* 在某些场景下,我们需要手动编写 Mapper,可以通过这个注解来关闭 APT 的 Mapper 生成。
*/
boolean mapperGenerateEnable() default true;
}
2.1.1、使用示例
使用前面的示例代码进行调整。t_user表中有字段extension为扩展字段,我们利用该字段进行填充测试。
1)User实体类添加@Table注解,并指定OnInsert填充监听器。
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(value = "t_user", onInsert = UserEntityOnInsertListener.class)
public class User implements Serializable {
...
}
2)创建监听器UserEntityOnInsertListener。
UserEntityOnInsertListener实现InsertListener接口,并实现onInsert方法。
package org.shamee.demo.listener;
import com.mybatisflex.annotation.InsertListener;
import org.shamee.demo.entity.User;
public class UserEntityOnInsertListener implements InsertListener {
/**
* 重写该方法,自动填充extension字段
* @param entity 实体类
*/
@Override
public void onInsert(Object entity) {
User user = (User) entity;
user.setExtension("我是通过@Table注解的OnInsert监听器填充内容");
}
}
3)controller层方法。
/**
* 新增
* @return
*/
@GetMapping("insert")
public Boolean insert(){
User user = User.builder().userId("zhangsan").userName("张三").atk(100).battleNum(200).build();
userService.insert(user);
return Boolean.TRUE;
}
4)运行后查看数据填充。
需要注意的是:onInsert 监听中,通过 mybatis 的 xml mapper 插入数据,或者通过 Db + Row 中插入数据,并不会触发 onInsert 行为,只有通过 UserMapper 进行插入数据才会触发。
@Table注解的onUpdate属性与onInsert一致,onUpdate是应用于更新的场景。
2.2、@Column的onInsertValue填充
@Column应用于字段的注解,提供了onInsertValue属性,可以对字段设置默认值。在 insert 中,onInsertValue 配置的内容会直接参与 SQL 拼接,而不是通过 JDBC 的 Statement 参数设置,需要开发者注意 onInsertValue 的内容,否则可能会造成 SQL 错误。
@Table的注解和@Column注解的填充有什么区别?
@Table 注解的 onInsert 主要是在 Java 应用层面进行数据设置。
@Column 注解的 onInsertValue 则是在数据库层面进行数据设置。
2.2.1、使用示例
1)User实体类extension字段添加@Column注解。
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(value = "t_user")
public class User implements Serializable {
/**
* 由于这里会直接拼接成为sql的一部分,因此这里字符串必须添加引号,不然sql执行会出错
*/
@Column(onInsertValue = "'我是通过@Column注解的onInsertValue属性填充内容'")
private String extension;
}
2)controller层方法。
/**
* 新增
* @return
*/
@GetMapping("insert")
public Boolean insert(){
User user = User.builder().userId("zhangsan").userName("张三").atk(100).battleNum(200).build();
userService.insert(user);
return Boolean.TRUE;
}
3)运行后查看数据填充。
3、数据脱敏
数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形, 实现敏感隐私数据的可靠保护。在涉及客户安全数据或者一些商业性敏感数据的情况下,在不违反系统规则条件下,对真实数据进行改造并提供使用, 如身份证号、手机号、卡号、客户号等个人信息都需要进行数据脱敏。
Mybatis Flex提供了 @ColumnMask() 注解,并内置了以下脱敏规则:
并支持自定义规则。
3.1、使用示例
t_user表的userName字段进行中文名脱敏,使用内置的中文名脱敏规则。
/**
* @Table 注解自动映射实体类和表字段
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(value = "t_user")
public class User implements Serializable {
...
@Column(value = "userName")
@ColumnMask(Masks.CHINESE_NAME)
private String userName;
...
}
通过接口查询可以看到userName字段已脱敏。
4、多数据源
MyBaits-Flex 内置了功能完善的多数据源支持^1.0.6,不需要借助第三方插件或者依赖,开箱即用, 支持包括 druid、hikaricp、dbcp2、beecp 在内的任何数据源,使用Mybatis-Flex多数据源配置如下:
mybatis-flex:
datasource:
ds1:
url: jdbc:mysql://127.0.0.1:3306/db
username: root
password: 123456
ds2:
url: jdbc:mysql://127.0.0.1:3306/db2
username: root
password: 123456
其中,ds1 和 ds2 是由用户自定义的数据源名称,使用方式如下:
List<Row> rows = DataSourceKey.use("ds2", () -> Db.selectAll("t_user"));
但是通常我们会直接使用Spring Boot的多数据源配置方式。
5、读写分离
MyBatis-Flex 的读写分离功能是基于多数据源功能来实现的。读写分离的功能,要求当前环境必须是多个数据库(也可理解为多个数据源),其原理是: 让主数据库(master)处理事务性操作,比如:增、删、改(INSERT、DELETE、UPDATE),而从数据库(slave)处理查询(SELECT)操作。
例如,数据源配置:
mybatis-flex:
datasource:
master:
type: druid
url: jdbc:mysql://127.0.0.1:3306/master-db
username: root
password: 123456
slave1:
type: com.your.datasource.type2
url: jdbc:mysql://127.0.0.1:3306/slave1
username: root
password: 123456
slave2:
type: com.your.datasource.type2
url: jdbc:mysql://127.0.0.1:3306/slave2
username: root
password: 123456
other:
type: com.your.datasource.type2
url: jdbc:mysql://127.0.0.1:3306/other
username: root
password: 123456
以上配置中,一共有 4 个数据源,分别为 master、slave1、slave2、other。 我们的需求是:在 增删改 时,走 master 数据源,而在查询时,随机自动使用 slave1、slave2 数据源进行负载均衡。
那么,我们的分片策略代码如下:
public class MyStrategy implements DataSourceShardingStrategy {
public String doSharding(String currentDataSourceKey
, Object mapper, Method mapperMethod, Object[] methodArgs){
// 不管 other 数据源的情况
if ("other".equals(currentDataSourceKey)){
return currentDataSourceKey;
}
// 如果 mapper 的方法属于 增删改,使用 master 数据源
if (StringUtil.startWithAny(mapperMethod.getName(),
"insert", "delete", "update")){
return "master";
}
//其他场景,使用 slave1 或者 slave2 进行负载均衡
return "slave*";
}
}
6、更多特性
此外,还有更多的特性如SQL审计,SQL打印,数据源加密,动态表名等特性,官网写的也很详细了,本文中很多也都是摘抄自官网,只是结合一些自己的动手demo,便于自己理解和掌握。更多的特性可见地址:快速开始 - MyBatis-Flex 官方网站