General Mapper @KeySql annotation genId method detailed

In order to facilitate the use of global primary keys (for example: Vesta is a universal ID generator, commonly known as a unified number issuer on the Internet), the Universal Mapper 4.0.2 version adds a new strategy for controlling the generation of primary keys.

@KeySqlThe annotation adds the following methods:

/**
 * Java 方式生成主键,可以和发号器一类的服务配合使用
 *
 * @return
 */
Class<? extends GenId> genId() default GenId.NULL.class;

When using this function, you need to configure the genIdproperties .
Since the way of generating the primary key is usually related to the usage environment, the generic Mapper does not provide a default implementation.

GenIdThe interface is as follows:

public interface GenId<T> {
    class NULL implements GenId {
        @Override
        public Object genId(String table, String column) {
            throw new UnsupportedOperationException();
        }
    }

    T genId(String table, String column);
}

It can be seen from the interface method that when the Id is generated, the current table name and column name can be obtained, and we can use these two information to generate the Id information related to the table field. You can also generate a global Id without using these two pieces of information at all.

When using the genId method, the value of the field can be written back!

Example 1, using UUID

Full test code:
https://github.com/abel533/Mapper/tree/master/base/src/test/java/tk/mybatis/mapper/base/genid

1. ImplementationGenId

When using the UUID method, first we need to provide an implementation class that can generate UUID:

public class UUIdGenId implements GenId<String> {
    @Override
    public String genId(String table, String column) {
        return UUID.randomUUID().toString();
    }
}

This implementation class simply returns a value of Stringtype and doesn't deal with UUIDs -.

2. ConfigurationgenId

For example, there is the following table (hsqldb database):

create table user (
  id   varchar(64) NOT NULL PRIMARY KEY,
  name varchar(32),
  code VARCHAR(2)
);

Corresponds to the following entities:

public class User {
    @Id
    @KeySql(genId = UUIdGenId.class)
    private String id;
    private String name;
    private String code;

    public User() {
    }

    public User(String name, String code) {
        this.name = name;
        this.code = code;
    }
    //省略 setter 和 getter
}

We only need @KeySql(genId = UUIdGenId.class)to It should be noted that if you use @KeySqlother methods provided by , genIdit will not take effect, and it genIdis the lowest priority of all methods.

3. Test

@Test
public void testUUID(){
    SqlSession sqlSession = getSqlSession();
    try {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        for (int i = 0; i < countries.length; i++) {
            User user = new User(countries[i][0], countries[i][1]);
            Assert.assertEquals(1, mapper.insert(user));
            Assert.assertNotNull(user.getId());
            System.out.println(user.getId());
        }
    } finally {
        sqlSession.close();
    }
}

Some of the output logs are as follows:

DEBUG [main] - Setting autocommit to false on JDBC Connection [org.hsqldb.jdbc.JDBCConnection@3eb7fc54]
DEBUG [main] - ==>  Preparing: INSERT INTO user ( id,name,code ) VALUES( ?,?,? ) 
DEBUG [main] - ==> Parameters: 94ee80ac-d156-412d-b63e-b75b49026874(String), Angola(String), AO(String)
DEBUG [main] - <==    Updates: 1
94ee80ac-d156-412d-b63e-b75b49026874
DEBUG [main] - ==>  Preparing: INSERT INTO user ( id,name,code ) VALUES( ?,?,? ) 
DEBUG [main] - ==> Parameters: 0f21aab9-0637-4b7f-ade9-fe5bc4cf1693(String), Afghanistan(String), AF(String)
DEBUG [main] - <==    Updates: 1
0f21aab9-0637-4b7f-ade9-fe5bc4cf1693

Example 2, simple global timing ID

Full test code:
https://github.com/abel533/Mapper/tree/master/base/src/test/java/tk/mybatis/mapper/base/genid

1. ImplementationGenId

When using the UUID method, first we need to provide an implementation class that can generate UUID:

public class SimpleGenId implements GenId<Long> {
    private Long    time;
    private Integer seq;

    @Override
    public synchronized Long genId(String table, String column) {
        long current = System.currentTimeMillis();
        if (time == null || time != current) {
            time = current;
            seq = 1;
        } else if (current == time) {
            seq++;
        }
        return (time << 20) | seq;
    }
}

This is a simple implementation that is guaranteed to be unique via synchronized methods, does not consider any special cases, and should not be used in production environments.

2. ConfigurationgenId

For example, there is the following table (hsqldb database):

create table country (
  id          bigint NOT NULL PRIMARY KEY,
  countryname varchar(32),
  countrycode VARCHAR(2)
);

Corresponds to the following entities:

public class Country {
    @Id
    @KeySql(genId = SimpleGenId.class)
    private Long id;
    private String countryname;
    private String countrycode;

    public Country() {
    }

    public Country(String countryname, String countrycode) {
        this.countryname = countryname;
        this.countrycode = countrycode;
    }
    //省略 setter 和 getter
}

We only need @KeySql(genId = SimpleGenId.class)to It should be noted that if you use @KeySqlother methods provided by , genIdit will not take effect, and it genIdis the lowest priority of all methods.

3. Test

@Test
public void testGenId(){
    SqlSession sqlSession = getSqlSession();
    try {
        CountryMapper mapper = sqlSession.getMapper(CountryMapper.class);
        for (int i = 0; i < countries.length; i++) {
            Country country = new Country(countries[i][0], countries[i][1]);
            Assert.assertEquals(1, mapper.insert(country));
            Assert.assertNotNull(country.getId());
            System.out.println(country.getId());
        }
    } finally {
        sqlSession.close();
    }
}

Some of the output logs are as follows:

DEBUG [main] - Setting autocommit to false on JDBC Connection [org.hsqldb.jdbc.JDBCConnection@96def03]
DEBUG [main] - ==>  Preparing: INSERT INTO country ( id,countryname,countrycode ) VALUES( ?,?,? ) 
DEBUG [main] - ==> Parameters: 1598437075106922497(Long), Angola(String), AO(String)
DEBUG [main] - <==    Updates: 1
1598437075106922497
DEBUG [main] - ==>  Preparing: INSERT INTO country ( id,countryname,countrycode ) VALUES( ?,?,? ) 
DEBUG [main] - ==> Parameters: 1598437075176128513(Long), Afghanistan(String), AF(String)
DEBUG [main] - <==    Updates: 1
1598437075176128513
DEBUG [main] - ==>  Preparing: INSERT INTO country ( id,countryname,countrycode ) VALUES( ?,?,? ) 
DEBUG [main] - ==> Parameters: 1598437075178225665(Long), Albania(String), AL(String)
DEBUG [main] - <==    Updates: 1
1598437075178225665

Example 3, Vesta-based implementation

It should be seen from the previous two examples that different ID generation methods can be switched through different GenIdimplementations , and the type of ID needs to be consistent.

Here is an idea that can be applied to the production environment. Since it is related to the specific environment, there is no directly available code here.

Vesta address: https://gitee.com/robertleepeak/vesta-id-generator

Sample code:

public class VestaGenId implement GenId<Long> {
   public Long genId(String table, String column){
       //ApplicationUtil.getBean 需要自己实现
       IdService idService = ApplicationUtil.getBean(IdService.class);
       return idService.genId();
   }
}

This code is also very simple. Since the annotation can only configure the class and cannot be injected, VestaGenIdit cannot be injected directly in the implementation. IdServiceIt needs to be obtained from the Spring Context through a static method, and it can be used normally after obtaining it.

ApplicationUtil.getBeanMethods are easily understood by those familiar with Spring .
If you don't know about Spring, you can take a look at SpringContextHolder here http://sb33060418.iteye.com/blog/2372874 .

special place

genIdWhen using , the ID value has been generated before interacting with the database. Since this ID has nothing to do with the mechanism of the database, any number genIdof @KeySqlannotations of the usage can appear in an entity, and these annotations can specify different implementation methods.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324727569&siteId=291194637