springboot jpa oracle实体类中配置注解无法在数据库中生成注释的一种解决方式

Posted 行走的五花肉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot jpa oracle实体类中配置注解无法在数据库中生成注释的一种解决方式相关的知识,希望对你有一定的参考价值。

需求

对于oracle数据库,jpaEntity即使配置了注释注解@Column(columnDefinition = \'列注释\'),无法在数据库层生成列的注释

解决方案

自定义注解,配置在Entity类上,项目初始化时,通过EntityManager获取所有的实体类,遍历实体类中是否配置了注解,如果配置了,动态拼接DDL语句并执行

  • 自定义注解:

    import java.lang.annotation.*;
    /**
    * description: * 解决jap根据实体类创建建表过程中无法添加字段注释
    * @author MorningSun
    * @version 1.0 * @since JDK1.8 * date 11/6/2020 10:45 AM */@Target({ElementType.TYPE, ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface JPAOracleComment {
       /**
    * spring jpa + oracle add comment * @return */ String value() default "";
    }
    import com.orient.cssrc.jpa.model.JpaOracleComment;
    import lombok.extern.slf4j.Slf4j;
    import org.hibernate.SessionFactory;
    import org.hibernate.internal.SessionFactoryImpl;
    import org.hibernate.persister.entity.EntityPersister;
    import org.hibernate.persister.entity.SingleTableEntityPersister;
    import org.hibernate.persister.walking.spi.AttributeDefinition;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.stereotype.Component;
    import javax.annotation.Resource;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.PersistenceContext;
    import java.lang.reflect.Field;
    import java.util.Map;
    import java.util.Objects;
    /**
    * description: * * @author MorningSun * @version V1.0 * @since date 2020/12/25 */@Slf4j
    @Component
    public class JpaOracleCommentInit implements CommandLineRunner {
       @PersistenceContext
    private EntityManager entityManager;
       @Resource
    private JdbcTemplate jdbcTemplate;
       @Resource
    private HibernateProperties hibernateProperties;
       @Override
    public void run(String... args) throws Exception {
           String ddlAuto = this.hibernateProperties.getDdlAuto();
           if(Objects.nonNull(ddlAuto) && "update".equalsIgnoreCase(ddlAuto)){
               this.scanCommentAnnotationOnEntityAndCreate();
           }
       }
       private void scanCommentAnnotationOnEntityAndCreate(){
           EntityManagerFactory entityManagerFactory = this.entityManager.getEntityManagerFactory();
           SessionFactoryImpl sessionFactory = (SessionFactoryImpl)entityManagerFactory.unwrap(SessionFactory.class);
           Map<String, EntityPersister> persisterMap = sessionFactory.getMetamodel().entityPersisters();
           if(Objects.nonNull(persisterMap) && persisterMap.keySet().size() > 0){
               for(Map.Entry<String, EntityPersister> entry: persisterMap.entrySet()){
                   Class<?> targetClazz = entry.getValue().getMappedClass();
                   SingleTableEntityPersister persister = (SingleTableEntityPersister)entry.getValue();
                   //数据表名
    String tableName = persister.getTableName();
                   //添加表的注释
    JpaOracleComment targetClazzAnno = targetClazz.getAnnotation(JpaOracleComment.class);
                   if(Objects.nonNull(targetClazzAnno)){
                       String sql = "comment on table " +
                               tableName +
                               " is " +
                               "\'" + targetClazzAnno.value() + "\'";
                       this.jdbcTemplate.execute(sql);
                   }
                   for (AttributeDefinition attributeDefinition : persister.getAttributes()) {
                       //属性名称
    String propertyName = attributeDefinition.getName();
                       if (propertyName.equalsIgnoreCase("_identifierMapper")) {
                           log.warn("尝试为实体类:" + targetClazz.getSimpleName() + "生成注解,发现了联合主键,暂时无法处理,已忽略对应字段");
                           continue;
                       }
                       Field field;
                       try {
                           field = targetClazz.getDeclaredField(propertyName);
                           JpaOracleComment anno = field.getAnnotation(JpaOracleComment.class);
                           if (Objects.nonNull(anno)) {
                               //数据库字段名
    String[] columns = persister.getPropertyColumnNames(propertyName);
                               String sql = "comment on column " +
                                       tableName +
                                       "." +
                                       columns[0] +
                                       " is " +
                                       "\'" + anno.value() + "\'";
                               this.jdbcTemplate.execute(sql);
                           }
                       } catch (NoSuchFieldException ex) {
                           ex.printStackTrace();
                       }
                   }
               }
           }
       }
    }

以上是关于springboot jpa oracle实体类中配置注解无法在数据库中生成注释的一种解决方式的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot + JPA问题汇总

JPA 2.1 - 无法调用 Oracle 函数

springcloud JPA 懒加载失败

JPA-在非实体类中连接两个表

JPA:查询以根据实体类中定义的外键值获取结果?

如何使用类中的 setters 方法将数据插入 JPA 实体表?