본문 바로가기
놀기/잡스러운 것

오라클 Comment 자동 생성을 위한 Custom Annotation 만들기

by Hi~ 2021. 10. 16.

SpringBoot 환경에서 오라클을 사용하는데, table은 자동으로 만들어 줘서 좋은데 Comment는 자동으로 안 넣어줘 이래 저래 찾다 보니 딱히 방법이 없었다. Mysql 같은 경우, table을 만들면서 comment를 추가할 수 있어 @Column Annotation에 'columndefinition'을 넣어 만들 수 있는데 Oracle은 그 방법을 쓸 수 없고 'comment on' query를 써야 한다. 그러던 중 좋은 게시물을 찾았다.

 

https://developpaper.com/a-solution-to-the-problem-that-configuration-annotation-in-springboot-jpa-oracle-entity-class-cannot-generate-annotation-in-database/

 

A solution to the problem that configuration annotation in springboot JPA Oracle entity class cannot generate annotation in data

demand aboutoracleDatabase,jpaOfEntityEven if comments are configured@Column (columndefinition ='column comment '), unable to generate comments for columns in the database tier Solution User defined annotation, configured inEntityClass, when the project is

developpaper.com

 

문제는 잘 동작하느냐!!! 한 번 해봅시다.

 

목차

     

     

    Springboot 프로젝트 만들기


    기존 프로젝트에 넣으면 환경에 따라되고 안되고 그런 상황이 생기니 새로운 프로젝트를 하나 만들자.

     

     

    기본 빌드 및 실행 확인


    당연히 잘 되겠지만, 확인해보자.

     

     

     

    실행하니 에러가 나오네요. DB 설정이 빠져서 그런가 보다.

     

     

    application.properties 수정하기


    간단하게 필요한 내용만 추가하자.

     

    이제 잘 동작한다.

     

     

     

    테이블 만들기


    아래와 같이 소스코드를 추가해서 TBL_TEST을 만든다.

    package com.example.demo;
    
    import lombok.Data;
    import javax.persistence.*;
    
    @Data
    @Entity
    @Table(name = "TBL_TEST")
    public class tblTest {
    
        @Id
        @Column(name = "SEQ")
        private Long seq;
    
        @Column(name = "TEST_INT_VAL")
        private Integer testIntVal;
    
        @Column(name = "TEST_STR_VAL")
        private String testStrVal;
    
    }

     

    소스코드 추가 후, 빌드해서 실행하면 DB에 테이블이 추가된 것을 확인할 수 있다.

     

     

    Comment 자동 생성을 위한 Custom Annotation 만들기


    드디어 본론이다. Comment란 이름으로 Annotation을 만들 계획이니 일단, 써 놓으면 에러 표시가 나며 마우스를 올리면 아래와 같이 나온다. 여기서 "Create annotation 'Comment'를 선택한다.

     

     

    자동 생성된 Comment.java 파일을 아래와 같이 작성한다.

    package com.example.demo;
    
    import java.lang.annotation.*;
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.FIELD})
    public @interface Comment {
        String value() default "";
    }

     

    그리고, DemoApplication.java 파일을 아래와 같이 수정한다. 코드를 보면 알겠지만, Annotation을 찾아 'comment on' query를 생성하여 실행하는 코드다. 

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    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 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;
    
    @SpringBootApplication
    public class DemoApplication implements CommandLineRunner {
        @PersistenceContext private EntityManager entityManager;
        @Resource private JdbcTemplate jdbcTemplate;
        @Resource private HibernateProperties hibernateProperties;
    
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args).close();
        }
    
        @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 = entityManagerFactory.unwrap(SessionFactoryImpl.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();
                    //Data table name
                    String tableName = persister.getTableName();
                    //Add a comment for the table
                    Comment targetClazzAnno = targetClazz.getAnnotation(Comment.class);
                    if (Objects.nonNull(targetClazzAnno)) {
                        String sql = "comment on table " +
                            tableName +
                            " is " +
                            "'" + targetClazzAnno.value() + "'";
                            this.jdbcTemplate.execute(sql);
                    }
                    for (AttributeDefinition attributeDefinition : persister.getAttributes()) {
                        //Property name
                        String propertyName = attributeDefinition.getName();
                        if (propertyName.equalsIgnoreCase("_identifierMapper")) {
                            continue;
                        }
                        Field field;
                        try {
                            field = targetClazz.getDeclaredField(propertyName);
                            if (Objects.nonNull(field)) {
                                Comment anno = field.getAnnotation(Comment.class);
                                if (Objects.nonNull(anno)) {
                                    //Database field name
                                    String[] columns = persister.getPropertyColumnNames(propertyName);
                                    String sql = "comment on column " +
                                        tableName +
                                        "." +
                                        columns[0] +
                                        " is " +
                                        "'" + anno.value() + "'";
                                        this.jdbcTemplate.execute(sql);
    
    
                                    System.out.printf("[Table (%s) - %s = %s\n", tableName, columns[0], anno.value());
                                }
                            }
                        } catch (NoSuchFieldException ex) {
                            //ex.printStackTrace();
                        }
                    }
                }
            }
        }
    }

     

    실행하면 아래오 같이 console에 나온다. 원하던 대로 되는 것 같다.

     

     

    TBL_TEST 테이블 확인


    짜잔!! 원하던 데로 comment가 추가되었다.

     

     

     

    마무리


    좋은 게시물을 찾았고 따라 했을 때 원하던 결과를 얻으니 이보다 좋은 것이 어디 있겠는가!!!!!!!

    혹시, 무식해서 귀찮은 방식으로 한 것은 아닌지 모르겠다. 더 편한 방법을 아시면 덧글 좀 부탁해요.

    댓글