文章目录
- Mybatis Flex 常见用法
- 一、枚举
- 二、自动填充
- 2.1 方式一:@Table 配置
- 2.2 方式二:@Column 配置
- 三、分页
- 3.1 分页统一接口
- 3.2 实现分页接口
- 3.3 使用
- 四、关联查询
- 4.1 @RelationOneToOne:一对一
- 4.1.1 单向关联
- 4.1.2 双向关联
- 4.2 @RelationOneToMany && @RelationManyToOne:一对多 和 多对一
- 4.2.1 单向关联
- 4.2.2 双向关联
- 4.3 @RelationManyToMany:多对多
- 4.3.1 单向关联
- 4..3.2 双向关联
- 4.4 ByQuery
- 五、多数据源
- 5.1 配置
- 5.1.1 application.yml (必须)
- 5.1.2 @Table(dataSource = "slave01")(选择配置)
- 5.1.2 @UseDataSource(选择配置)
- 5.3 使用
- 六、读写分离
- 6.1 读写分离策略
- 6.2 配置
- 七、其他
- 5.1 逻辑删除
- 5.2 数据脱敏
Mybatis Flex 常见用法
一、枚举
-
枚举类
@Getter @AllArgsConstructor public enum GradeEnum {UNKNOWN(0, "未知"),SECONDARY(2, "中学"),PRIMARY(1, "小学"),HIGH(3, "高中");@EnumValue // 数据库存储字段private final Integer code;@JsonValue // 转 Json 字段private final String name; }
-
使用
@Data @Table(value = "t_student") public class Student {@Id(keyType = KeyType.Auto)private Integer id;// 枚举private GradeEnum grade; }
二、自动填充
2.1 方式一:@Table 配置
-
监听器
public class AutoFillListener implements InsertListener, UpdateListener {@Overridepublic void onInsert(Object o) {BaseEntity baseEntity = (BaseEntity) o;// TODO 获取当前用户String username = "测试用户";Date now = new Date();baseEntity.setCreatedBy(username);baseEntity.setCreatedTime(now);baseEntity.setUpdatedBy(username);baseEntity.setUpdatedTime(now);}@Overridepublic void onUpdate(Object o) {BaseEntity baseEntity = (BaseEntity) o;// TODO 获取当前用户String username = "测试用户";Date now = new Date();baseEntity.setUpdatedBy(username);baseEntity.setUpdatedTime(now);} }
-
注解配置
@EqualsAndHashCode(callSuper = true) @Data @Table(value = "t_product", onInsert = AutoFillListener.class, onUpdate = AutoFillListener.class) public class Product extends BaseEntity {@Id(keyType = KeyType.Auto)private Integer id;private String name;private GradeEnum grade; } @Data public abstract class BaseEntity implements Serializable {// 创建人private String createdBy;// 创建时间private Date createdTime;// 更新人private String updatedBy;// 更新时间private Date updatedTime; }
2.2 方式二:@Column 配置
@Data
public abstract class BaseEntity implements Serializable {@Column(onInsertValue = "'测试'")// 创建人private String createdBy;// 创建时间@Column(onInsertValue = "now()")private Date createdTime;// 更新人@Column(onInsertValue = "'测试'", onUpdateValue = "'测试'")private String updatedBy;// 更新时间@Column(onInsertValue = "now()", onUpdateValue = "now()")private Date updatedTime;
}
三、分页
3.1 分页统一接口
public interface AppPage<T> {/*** 当前页页码*/long getPageNum();/*** 每页条数*/long getPageSize();/*** 总条数*/long getTotal();/*** 总页数*/long getTotalPages();/*** 分页对象记录*/List<T> getItems();
}
3.2 实现分页接口
@AllArgsConstructor
public class MybatisFlexPageImpl<T> implements AppPage<T> {private Page<T> page;@Overridepublic long getPageNum() {if (page == null) return 0;return page.getPageNumber();}@Overridepublic long getPageSize() {if (page == null ) return 0;return page.getPageSize();}@Overridepublic long getTotal() {if (page == null ) return 0;return page.getTotalRow();}@Overridepublic long getTotalPages() {if (page == null ) return 0;return page.getTotalPage();}@Overridepublic List<T> getItems() {return page.getRecords();}
}
3.3 使用
@RestController
@RequestMapping("product")
public class ProductController {@GetMapping("page")public AppPage<Product> page (){Page<Product> paginate = productRepo.paginate(1, 2, QueryCondition.createEmpty());return new MybatisFlexPageImpl<Product>(paginate);}
}
四、关联查询
4.1 @RelationOneToOne:一对一
4.1.1 单向关联
-
User
@Data @Table(value = "t_user") public class User {@Id(keyType = KeyType.Auto)private Integer id;@RelationOneToOne(selfField = "id", targetField = "userId") // selfField 为主键可省略private UserInfo userInfo; }
-
UserInfo
@Data @Table(value = "t_user_info") public class UserInfo {@Id(keyType = KeyType.Auto)private Integer id;private Integer userId; // 一对一关系,对应的关联字段 }
4.1.2 双向关联
-
User
@Data @Table(value = "t_user") public class User {@Id(keyType = KeyType.Auto)private Integer id;@RelationOneToOne(selfField = "id", targetField = "userId") // selfField 为主键可省略private UserInfo userInfo; }
-
UserInfo
@Data @Table(value = "t_user_info") public class UserInfo {@Id(keyType = KeyType.Auto)private Integer id;@RelationOneToOne(selfField = "userId", targetField = "id")private User user;private Integer userId; }
4.2 @RelationOneToMany && @RelationManyToOne:一对多 和 多对一
4.2.1 单向关联
-
@RelationOneToMany
Group
@Data @Table(value = "t_group") public class Group {@Id(keyType = KeyType.Auto)private Integer id;// 单向关联@RelationOneToMany(selfField = "id", targetField = "groupId")List<Student> studentList; }
Student
@Data @Table(value = "t_student") public class Student {@Id(keyType = KeyType.Auto)private Integer id;private Integer groupId; // 单向关联字段 }
-
@RelationManyToOne
Student
@Data @Table(value = "t_student") public class Student {@Id(keyType = KeyType.Auto)private Integer id;// 单向关联@RelationManyToOne(selfField = "groupId", targetField = "id")private Group group;private Integer groupId; }
Group
@Data @Table(value = "t_group") public class Group {@Id(keyType = KeyType.Auto)private Integer id; }
4.2.2 双向关联
-
Student
@Data @Table(value = "t_student") public class Student {@Id(keyType = KeyType.Auto)private Integer id;// 双向关联@RelationManyToOne(selfField = "groupId", targetField = "id")private Group group;private Integer groupId; }
-
Group
@Data @Table(value = "t_group") public class Group {@Id(keyType = KeyType.Auto)private Integer id;// 单向关联@RelationOneToMany(selfField = "id", targetField = "groupId")List<Student> studentList; }
4.3 @RelationManyToMany:多对多
4.3.1 单向关联
@Data
@Table(value = "t_user")
public class User {@Id(keyType = KeyType.Auto)private Integer id;@RelationManyToMany(joinTable = "t_user_role", // 中间表selfField = "id", joinSelfColumn = "user_id", // selfField 为主键时可省略targetField = "id", joinTargetColumn = "role_id") // targetField 为主键时可省略private List<Role> roles;
}
4…3.2 双向关联
-
User
@Data @Table(value = "t_user") public class User {@Id(keyType = KeyType.Auto)private Integer id;@RelationManyToMany(joinTable = "t_user_role", // 中间表selfField = "id", joinSelfColumn = "user_id", // selfField 为主键时可省略targetField = "id", joinTargetColumn = "role_id") // targetField 为主键时可省略private List<Role> roles; }
-
Role
@Data @Table(value = "t_role") public class Role {@Id(keyType = KeyType.Auto)private Integer id;@RelationManyToMany(joinTable = "t_user_role",joinSelfColumn = "role_id",joinTargetColumn = "user_id")private List<User> userList; }
4.4 ByQuery
@SpringBootTest
public class TableAssociation { @Autowiredprivate StudentMapper studentMapper;@Autowiredprivate GroupMapper groupMapper;@Test // 关联查询public void associationQuery() {// 查询 Student 及对应的 GroupList<Student> students = studentMapper.selectListByQuery(QueryWrapper.create(),fb -> fb.field(Student::getGroup).queryWrapper(student ->{Group group = new Group();group.setId(student.getId());return QueryWrapper.create(group);}));System.out.println(students);// 查询 Group 及对应的 StudentList<Group> groups = groupMapper.selectListByQuery(QueryWrapper.create(),f -> f.field(Group::getStudentList).queryWrapper(group -> {Student student = new Student();student.setGroupId(group.getId());return QueryWrapper.create(student);}));System.out.println(groups);}
}
五、多数据源
DataSourceKey.use() > @UseDataSource()在方法上 > @UseDataSource()在类上 >@Table(dataSource=“…”)
5.1 配置
5.1.1 application.yml (必须)
mybatis-flex:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpldatasource:master:url: jdbc:mysql://localhost:3336/test?serverTimezone=UTCusername: rootpassword: 123456slave01:url: jdbc:mysql://localhost:3337/test?serverTimezone=UTCusername: rootpassword: 123456
5.1.2 @Table(dataSource = “slave01”)(选择配置)
@Data
@Table(value = "t_student",dataSource = "slave01")
public class Student {}
5.1.2 @UseDataSource(选择配置)
@Mapper
@UseDataSource("slave01") // 用于类
public interface GroupMapper extends BaseMapper<Group> {}@Mapper
public interface ProductMapper extends BaseMapper<Product> {@UseDataSource("master") // 用于方法@Select("select * from t_product") List<Product> findAll();
}
5.3 使用
@SpringBootTest
public class MoreSourceTest {@Autowiredprivate StudentMapper studentMapper;@Autowiredprivate UserMapper userMapper;@Autowiredprivate GroupMapper groupMapper;/*** 使用 @Table(dataSource = "master")*/@Testpublic void get() {List<Student> students = studentMapper.selectAll();System.out.println(students);List<User> users = userMapper.selectAll();System.out.println(users);}/*** 使用 @UseDataSource("master")*/@Testpublic void get2 (){List<Group> groups = groupMapper.selectAll();System.out.println(groups);}/*** 使用 DataSourceKey.use("master")*/@Testpublic void get3 (){List<Group> groups = groupMapper.selectAll();System.out.println(groups);try {DataSourceKey.use("master");List<Row> rows = Db.selectAll("t_Group");List<Group> groupList = rows.stream().map(e -> {Group group = new Group();BeanUtil.copyProperties(e, group);return group;}).toList();System.out.println(groupList);}finally {DataSourceKey.clear();}}
}
六、读写分离
6.1 读写分离策略
@Slf4j
public class ReaderAndWriterStrategy implements DataSourceShardingStrategy {private static final String MASTER = "master";private static final String SLAVE = "slave*";@Overridepublic String doSharding(String currentDataSourceKey, Object mapper, Method mapperMethod, Object[] methodArgs) {// 增删改 用 masterif (StringUtil.startsWithAny(mapperMethod.getName(),"insert","delete","update")){return MASTER;}// 其他场景使用 slave开头 的数据源进行负载均衡return SLAVE;}
}
6.2 配置
@Configuration
public class ReaderAndWriterConfig {@Beanpublic DataSourceManager dataSourceManager(){DataSourceManager dataSourceManager = new DataSourceManager();dataSourceManager.setDataSourceShardingStrategy(new ReaderAndWriterStrategy());return dataSourceManager;}
}
七、其他
5.1 逻辑删除
@Data
@Table(value = "t_student")
public class Student {@Id(keyType = KeyType.Auto)private Integer id;@Column(isLogicDelete = true)private boolean deleted;
}
5.2 数据脱敏
@Data
@Table(value = "t_student")
public class Student {@Id(keyType = KeyType.Auto)private Integer id;@ColumnMask(Masks.CHINESE_NAME) // 自带脱敏private String name;@ColumnMask("sexMask") // 自定义脱敏private String sex;static { // 自定义脱敏逻辑MaskManager.registerMaskProcessor("sexMask", data -> "*");}
}