枚举类
@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;
}
监听器
public class AutoFillListener implements InsertListener, UpdateListener {
@Override
public 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);
}
@Override
public 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;
}
@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;
}
public interface AppPage<T> {
/**
* 当前页页码
*/
long getPageNum();
/**
* 每页条数
*/
long getPageSize();
/**
* 总条数
*/
long getTotal();
/**
* 总页数
*/
long getTotalPages();
/**
* 分页对象记录
*/
List<T> getItems();
}
@AllArgsConstructor
public class MybatisFlexPageImpl<T> implements AppPage<T> {
private Page<T> page;
@Override
public long getPageNum() {
if (page == null) return 0;
return page.getPageNumber();
}
@Override
public long getPageSize() {
if (page == null ) return 0;
return page.getPageSize();
}
@Override
public long getTotal() {
if (page == null ) return 0;
return page.getTotalRow();
}
@Override
public long getTotalPages() {
if (page == null ) return 0;
return page.getTotalPage();
}
@Override
public List<T> getItems() {
return page.getRecords();
}
}
@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);
}
}
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; // 一对一关系,对应的关联字段
}
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;
}
@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;
}
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;
}
@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;
}
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;
}
@SpringBootTest
public class TableAssociation {
@Autowired
private StudentMapper studentMapper;
@Autowired
private GroupMapper groupMapper;
@Test // 关联查询
public void associationQuery() {
// 查询 Student 及对应的 Group
List<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 及对应的 Student
List<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=“…”)
mybatis-flex:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
datasource:
master:
url: jdbc:mysql://localhost:3336/test?serverTimezone=UTC
username: root
password: 123456
slave01:
url: jdbc:mysql://localhost:3337/test?serverTimezone=UTC
username: root
password: 123456
@Data
@Table(value = "t_student",dataSource = "slave01")
public class Student {}
@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();
}
@SpringBootTest
public class MoreSourceTest {
@Autowired
private StudentMapper studentMapper;
@Autowired
private UserMapper userMapper;
@Autowired
private GroupMapper groupMapper;
/**
* 使用 @Table(dataSource = "master")
*/
@Test
public void get() {
List<Student> students = studentMapper.selectAll();
System.out.println(students);
List<User> users = userMapper.selectAll();
System.out.println(users);
}
/**
* 使用 @UseDataSource("master")
*/
@Test
public void get2 (){
List<Group> groups = groupMapper.selectAll();
System.out.println(groups);
}
/**
* 使用 DataSourceKey.use("master")
*/
@Test
public 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();
}
}
}
@Slf4j
public class ReaderAndWriterStrategy implements DataSourceShardingStrategy {
private static final String MASTER = "master";
private static final String SLAVE = "slave*";
@Override
public String doSharding(String currentDataSourceKey, Object mapper, Method mapperMethod, Object[] methodArgs) {
// 增删改 用 master
if (StringUtil.startsWithAny(mapperMethod.getName(),"insert","delete","update")){
return MASTER;
}
// 其他场景使用 slave开头 的数据源进行负载均衡
return SLAVE;
}
}
@Configuration
public class ReaderAndWriterConfig {
@Bean
public DataSourceManager dataSourceManager(){
DataSourceManager dataSourceManager = new DataSourceManager();
dataSourceManager.setDataSourceShardingStrategy(new ReaderAndWriterStrategy());
return dataSourceManager;
}
}
@Data
@Table(value = "t_student")
public class Student {
@Id(keyType = KeyType.Auto)
private Integer id;
@Column(isLogicDelete = true)
private boolean deleted;
}
@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 -> "*");
}
}