通用mapper用oracle序列作为主键
程序员文章站
2022-07-06 09:38:22
通用mapper用oracle序列作为主键最近使用通用mapper开发项目,公司用的oracle数据库,持久层用的是通用mapper,公司要求用数据库的序列,按照官方的配置,可能是自己的原因,总是配置不对,自己看了一下源码,发现用key注解就可以实现,具体配置如下: @Id @Column(name = "id") @KeySql(sql = "select SEQ_ID.nextval from dual", order= ORDER.DEFAULT) private I...
通用mapper用oracle序列作为主键
最近使用通用mapper开发项目,公司用的oracle数据库,持久层用的是通用mapper,公司要求用数据库的序列,按照官方的配置,可能是自己的原因,总是配置不对,自己看了一下源码,发现用key注解就可以实现,具体配置如下:
@Id
@Column(name = "id")
@KeySql(sql = "select SEQ_ID.nextval from dual", order= ORDER.DEFAULT)
private Integer id;
平常用mybatis的时候,mybatis 有个selectKey标签,那么通用mapper应该是启动的时候把注解的内容封装成selectKey了。于是找到了BaseInsertProvider这个类。
public String insert(MappedStatement ms) {
Class<?> entityClass = getEntityClass(ms);
}
这个insert方法就是保存的方法,getEntityClass就是解析实体。点进去看一下。
public Class<?> getEntityClass(MappedStatement ms) {
EntityHelper.initEntityNameMap(returnType, mapperHelper.getConfig());
}
找到了initEntityNameMap 方法,再跟进去。
public static synchronized void initEntityNameMap(Class<?> entityClass, Config config) {
if (entityTableMap.get(entityClass) != null) {
return;
}
//创建并缓存EntityTable
EntityTable entityTable = resolve.resolveEntity(entityClass, config);
entityTableMap.put(entityClass, entityTable);
}
终于找到了解析resolve.resolveEntity(entityClass, config),点进去看看。
应为注解是写的在Id字段上的,我们就重点看解析field的方法。
for (EntityField field : fields) {
if (config.isUseSimpleType()){
//省略了一些方法
processField(entityTable, field, config, style);
}
然后看processField,找到处理主键的方法。
//处理主键策略
processKeyGenerator(entityTable, field, entityColumn);
protected void processKeyGenerator(EntityTable entityTable, EntityField field, EntityColumn entityColumn) {
//KeySql 优先级最高
if (field.isAnnotationPresent(KeySql.class)) {
processKeySql(entityTable, entityColumn, field.getAnnotation(KeySql.class));
} else if (field.isAnnotationPresent(GeneratedValue.class)) {
//执行 sql - selectKey
processGeneratedValue(entityTable, entityColumn, field.getAnnotation(GeneratedValue.class));
}
}
看到了keysql 这个注解,于是看下面是怎么处理的。
protected void processKeySql(EntityTable entityTable, EntityColumn entityColumn, KeySql keySql) {
if (keySql.useGeneratedKeys()) {
entityColumn.setIdentity(true);
entityColumn.setGenerator("JDBC");
entityTable.setKeyProperties(entityColumn.getProperty());
entityTable.setKeyColumns(entityColumn.getColumn());
} else if (keySql.dialect() == IdentityDialect.DEFAULT) {
entityColumn.setIdentity(true);
entityColumn.setOrder(ORDER.AFTER);
} else if (keySql.dialect() != IdentityDialect.NULL) {
//自动增长
entityColumn.setIdentity(true);
entityColumn.setOrder(ORDER.AFTER);
entityColumn.setGenerator(keySql.dialect().getIdentityRetrievalStatement());
} else if (StringUtil.isNotEmpty(keySql.sql())){
entityColumn.setIdentity(true);
entityColumn.setOrder(keySql.order());
entityColumn.setGenerator(keySql.sql());
} else if (keySql.genSql() != GenSql.NULL.class){
entityColumn.setIdentity(true);
entityColumn.setOrder(keySql.order());
try {
GenSql genSql = keySql.genSql().newInstance();
entityColumn.setGenerator(genSql.genSql(entityTable, entityColumn));
} catch (Exception e) {
log.error("实例化 GenSql 失败: " + e, e);
throw new MapperException("实例化 GenSql 失败: " + e, e);
}
} else if(keySql.genId() != GenId.NULL.class){
entityColumn.setIdentity(false);
entityColumn.setGenIdClass(keySql.genId());
} else {
throw new MapperException(entityTable.getEntityClass().getCanonicalName()
+ " 类中的 @KeySql 注解配置无效!");
}
}
}
这里面就是一些判断逻辑。于是我们用注解就可以实现了。
以上文章就是记录一下自己的心得,有不正之处,希望大家多多指点。
本文地址:https://blog.csdn.net/zlystudy/article/details/108974632