I. Main functions

  • The dictionary binding
  • Field encryption
  • Data desensitization
  • Table structure dynamic maintenance
  • Data audit record
  • Data scope (Data permissions)
  • Database sub-database sub-table, dynamic data source, read and write separation, database health check automatic switching.

Second, the use of

2.1 Dependency Import

  • Spring Boot introduces automatic dependency annotation packs
< the dependency > < groupId > com. Baomidou < / groupId > < artifactId > mybatis - mate - the starter < / artifactId > < version > 1.0.8 < / version > </dependency>Copy the code
  • Notes (Entity subcontracting use)
< the dependency > < groupId > com. Baomidou < / groupId > < artifactId > mybatis - mate - the annotation < / artifactId > < version > 1.0.8 < / version > </dependency>Copy the code

2.2 Dictionary Binding

  • For example, the result of the sex dictionary of type user_sex maps to the sexText property
@FieldDict(type = "user_sex", target = "sexText")
private Integer sex;

private String sexText;
Copy the code
  • Implement the IDataDict interface to provide dictionary data sources that can be injected into the Spring container.
@Component
public class DataDict implements IDataDict {

    /** * get */ from database or cache
    private Map<String, String> SEX_MAP = new ConcurrentHashMap<String, String>() {{
        put("0"."Female");
        put("1"."Male");
    }};

    @Override
    public String getNameByCode(FieldDict fieldDict, String code) {
        System.err.println("Field type:" + fieldDict.type() + ", code:" + code);
        returnSEX_MAP.get(code); }}Copy the code

2.3 Field Encryption

The @fieldENCRYPT annotation can be encrypted and stored, automatically decrypts the query results, and supports the globally configured encryption key algorithm and the annotation key algorithm, which can implement the IEncryptor injection custom algorithm.

@FieldEncrypt(algorithm = Algorithm.PBEWithMD5AndDES)
private String password;
Copy the code

2.4 Data desensitization

  • The @FieldSensitive annotation automatically desensitizes source data according to a preset policy. By default, SensitiveType has nine common desensitization policies built in. For example: Chinese name, bank card account number, mobile phone number, fixed phone number, mailing address, email, ID number, password, license plate number desensitization policy, you can also customize the policy as follows:
@FieldSensitive(type = "testStrategy")
private String username;

@FieldSensitive(type = SensitiveType.mobile)
private String mobile;
Copy the code
  • Custom desensitization policy testStrategy can be added to the default policy and injected into the Spring container.
@Configuration
public class SensitiveStrategyConfig {

    /** * Inject desensitization strategy */
    @Bean
    public ISensitiveStrategy sensitiveStrategy(a) {
        // Customize testStrategy type desensitization
        return new SensitiveStrategy().addStrategy("testStrategy", t -> t + "***test***"); }}Copy the code

2.5 Automatic MAINTENANCE of DDL data structures

  • Resolve upgrade table structure initialization, version release update SQL maintenance issues, currently support MySql, PostgreSQL.
@Component
public class PostgresDdl implements IDdl {

    /** * Execute SQL script */
    @Override
    public List<String> getSqlFiles(a) {
        return Arrays.asList(
                // Built-in package mode
                "db/tag-schema.sql".// Indicates the absolute path of the file
                "D:\\db\\tag-data.sql"); }}Copy the code
  • Not only can it be fixed, it can also be executed dynamically!!
ddlScript.run(new StringReader("DELETE FROM user; \n" +
                "INSERT INTO user (id, username, password, sex, email) VALUES\n" +
                "(20, 'Duo', '123456', 0, '[email protected]');"));
Copy the code
  • Is that it? Of course not, it also indicates multi-source execution!!
@Component
public class MysqlDdl implements IDdl {

    @Override
    public void sharding(Consumer<IDdl> consumer) {
        // If multiple data sources are specified, the master library initializes automatic synchronization from the slave library
        String group = "mysql";
        ShardingGroupProperty sgp = ShardingKey.getDbGroupProperty(group);
        if (null! = sgp) {/ / the main library
            sgp.getMasterKeys().forEach(key -> {
                ShardingKey.change(group + key);
                consumer.accept(this);
            });
            / / from the library
            sgp.getSlaveKeys().forEach(key -> {
                ShardingKey.change(group + key);
                consumer.accept(this); }); }}/** * Execute SQL script */
    @Override
    public List<String> getSqlFiles(a) {
        return Arrays.asList("db/user-mysql.sql"); }}Copy the code

2.6 Dynamic Multi-data Source Free Primary/Secondary Switchover

  • Sharding annotation support one sentence to enable data source to switch freely, you can add annotations in mapper layer, according to the needs of the type!!
@Mapper
@Sharding("mysql")
public interface UserMapper extends BaseMapper<User> {

    @Sharding("postgres")
    Long selectByUsername(String username);
}
Copy the code
  • You can also customize your strategy and move troops together
@Component
public class MyShardingStrategy extends RandomShardingStrategy {

    /** * Decide to switch data source key {@link ShardingDatasource}
     *
     * @paramGroup Dynamic database group *@param invocation     {@link Invocation}
     * @param sqlCommandType {@link SqlCommandType}
     */
    @Override
    public void determineDatasourceKey(String group, Invocation invocation, SqlCommandType sqlCommandType) {
        // Data source group group can be customized, keys is the primary and secondary nodes in the data source group, can be randomly selected or controlled by oneself
        this.changeDatabaseKey(group, sqlCommandType, keys -> chooseKey(keys, invocation)); }}Copy the code

You can enable master/slave policy and of course you can also enable health check!!

2.7 Data Rights

  • Add annotations to mapper layer:
// Test type data permission range, mixed paging mode
@datascope (type = "test", value = {@datacolumn (Alias = "u", name = "department_id"), @datacolumn (alias = "u", name = "mobile")} @datacolumn (alias = "u", name = "mobile")
@Select("select u.* from user u")
List<User> selectTestList(IPage<User> page, Long id, @Param("name") String username);
Copy the code
  • Simulate business processing logic:
@Bean
public IDataScopeProvider dataScopeProvider(a) {
    return new AbstractDataScopeProvider() {
        @Override
        protected void setWhere(PlainSelect plainSelect, Object[] args, DataScopeProperty dataScopeProperty) {
            // Args contains the request parameters of mapper method
            /* / SELECT U.* FROM user u WHERE (u.detment_id IN ('1', '2', '3', '5')) AND U.mobile LIKE '%1533%' */
            if ("test".equals(dataScopeProperty.getType())) {
                // The service type is test
                List<DataColumnProperty> dataColumns = dataScopeProperty.getColumns();
                for (DataColumnProperty dataColumn : dataColumns) {
                    if ("department_id".equals(dataColumn.getName())) {
                        // Append the department field IN condition, which can also be an SQL statement
                        Set<String> deptIds = new HashSet<>();
                        deptIds.add("1");
                        deptIds.add("2");
                        deptIds.add("3");
                        deptIds.add("5");
                        ItemsList itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList()));
                        InExpression inExpression = new InExpression(new Column(dataColumn.getAliasDotName()), itemsList);
                        if (null == plainSelect.getWhere()) {
                            // There is no WHERE condition
                            plainSelect.setWhere(new Parenthesis(inExpression));
                        } else {
                            // There is a where condition and processing
                            plainSelect.setWhere(newAndExpression(plainSelect.getWhere(), inExpression)); }}else if ("mobile".equals(dataColumn.getName())) {
                        // Support a custom condition
                        LikeExpression likeExpression = new LikeExpression();
                        likeExpression.setLeftExpression(new Column(dataColumn.getAliasDotName()));
                        likeExpression.setRightExpression(new StringValue("% 1533%"));
                        plainSelect.setWhere(newAndExpression(plainSelect.getWhere(), likeExpression)); }}}}}; }Copy the code
  • Finally execute SQL output:
SELECT u.* FROM user u 
  WHERE (u.department_id IN ('1'.'2'.'3'.'5')) 
  AND u.mobile LIKE '% 1533%' LIMIT 1.10
Copy the code

Three, the last

Hello everyone, I am Spring brother of Technology (open source author of MicA micro-service component). The author has been using Mybatis plus for more than 4 years (senior fan). Mybatis plus helps us greatly improve the development efficiency, unify the code development style in the enterprise, and reduce the maintenance cost.

If you have a Mybatis -mate usage scenario in your enterprise, you may wish to support it. Mybatis mate: gitee.com/baomidou/my…