通用mapper用oracle序列作为主键

通用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 注解配置无效!");
        }
    }

}

这里面就是一些判断逻辑。于是我们用注解就可以实现了。

以上文章就是记录一下自己的心得,有不正之处,希望大家多多指点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值