Mybatis Flex 常见用法

2023-12-22 15:07:04

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 {
        @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;
    }
    

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;

    @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();
    }
}

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 {   
    @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=“…”)

5.1 配置

5.1.1 application.yml (必须)
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
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 {

    @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();
        }
    }
}

六、读写分离

6.1 读写分离策略

@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;
    }
}

6.2 配置

@Configuration
public class ReaderAndWriterConfig {
    @Bean
    public 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 -> "*");
    }
}

文章来源:https://blog.csdn.net/qq_42151956/article/details/135150899
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。