多租户从字段的意思就是多家客户使用同一个系统,但是在系统查询时每个客户相互隔离,其实就是数据层面隔离,目前隔离方法有3种
1.DB SERVER完全隔离
2.DB Schema层面隔离
3.DB Table层面字段隔离
以上三种方式各有优缺点,不用说明都知道,主要从成本和可维护性上来对比, Mybatis-plus主要是采用第3种实现多租户
主要是通过接口TenantLineHandler 来实现
public interface TenantLineHandler {
Expression getTenantId();
default String getTenantIdColumn() {
return "tenant_id"; //指定多租户字段
}
default boolean ignoreTable(String tableName) {
return false; //false表示所有table都有多租户字段,这里可以利用tableName区分哪些table没有多租户字段
}
default boolean ignoreInsert(List<Column> columns, String tenantIdColumn) {
return columns.stream().map(Column::getColumnName).anyMatch((i) -> {
return i.equalsIgnoreCase(tenantIdColumn);
});
}
}
1.准备User类@Data
public class User extends Model<User> {
private Long id;
private String name;
private Integer age;
private String email;
private int deleted;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime createtime;
@Version
private long version;
private String fab;
}
2.增加多租户拦截器在Configuration类中
这里指定了多租户字段为FAB,多租户值通过getTenantId方法来设定
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
//interceptor.addInnerInterceptor((InnerInterceptor) new PerformanceMonitorInterceptor());
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
@Override
public Expression getTenantId() {
return new StringValue( "FAB1");
}
@Override
public String getTenantIdColumn() {
return "FAB";
}
@Override
public boolean ignoreTable(String tableName) {
return false;
}
}));
return interceptor;
}
3.生成insert测试方法
@Test
public void testSave(){
for(long i=20;i<21;i++) {
User user = new User();
user.setId(400+i);
user.setAge((int)i+30);
user.setEmail("zoulinlin"+i+"@163.com");
user.setName("zouli"+i);
int row = userMapper.insert(user);
System.out.println(row);
}
}
运行log:
2022-10-11 11:39:54.363 DEBUG 23900 --- [ main] c.m.service.mapper.UserMapper.insert : ==> Preparing: INSERT INTO user (id, name, age, email, deleted, createtime, version, FAB) VALUES (?, ?, ?, ?, ?, ?, ?, 'FAB1')
2022-10-11 11:39:54.393 DEBUG 23900 --- [ main] c.m.service.mapper.UserMapper.insert : ==> Parameters: 420(Long), zouli20(String), 50(Integer), zoulinlin20@163.com(String), 0(Integer), 2022-10-11T11:39:51.818(LocalDateTime), 0(Long)
4.生成查询测试方法
@Test
public void testQuery(){
HashMap<String,Object> hashMap=new HashMap<String,Object>();
//hashMap.put("name","jack");
hashMap.put("id",413);
List<User> users= userMapper.selectByMap(hashMap);
users.forEach(System.out::println);
}
运行log:
2022-10-11 11:42:00.134 DEBUG 19328 --- [ main] c.m.s.mapper.UserMapper.selectByMap : ==> Preparing: SELECT id, name, age, email, deleted, createtime, version, fab FROM user WHERE id = ? AND deleted = 0 AND user.FAB = 'FAB1'
2022-10-11 11:42:00.154 DEBUG 19328 --- [ main] c.m.s.mapper.UserMapper.selectByMap : ==> Parameters: 413(Integer)