[실무 JPA] 엔티티 생성

2021. 8. 4. 10:15개발공부/JPA 스터디

728x90

회사 어드민 서버가 C# .NET으로 이루어져 있는데 이번에 범용성이 넓고 저한테 익숙한 Java Spring으로 이전하는 작업을 맡게 되었습니다. 

그리고 SQL 처리를 MyBatis가 아닌 JPA를 사용하기로 했습니다. :) 소스코드 파악이 어느정도 되면 이관하는 작업을 진행하려 했습니다. 다만 Spring으로 이루어진 앱 서버의 DB는 파악하고 있기 때문에 우선 엔티티 이전 작업을 시작했습니다. 그 후 API 단위로 Controller, Service 단의 코드를 이전하려 합니다.

 

 

JPA 엔티티 생성

IntelliJ의 Database Tool을 사용하면 IDE에서 DB 데이터를 볼 수 있어 편합니다. 엔티티 생성도 

Database 연결

View > Tool Windows > Database
Data Sources 설정
DB 연동 완료

POJO Groovy 사용해 엔티티 생성 설정값 지정

Go To Scripts Directory 클릭 시 

 

Generate POJOs.groovy 코드

import com.intellij.database.model.DasTable
import com.intellij.database.model.ObjectKind
import com.intellij.database.util.Case
import com.intellij.database.util.DasUtil

import java.sql.Date
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

typeMapping = [
        (~/(?i)int|tinyint|smallint|mediumint/)  : "Integer",
        (~/(?i)bool|bit/)                        : "Boolean",
        (~/(?i)float|double|decimal|real|number/): "BigDecimal",
        (~/(?i)datetime|timestamp|date|time/)    : "LocalDateTime",
        (~/(?i)binary|bfile|raw|image/)          : "InputStream",
        (~/(?i)blob|clob/)                       : "lob",
        (~/(?i)/)                                : "String"
]


FILES.chooseDirectoryAndSave("Choose directory", "Choose where to store generated files") { dir ->
    SELECTION.filter { it instanceof DasTable && it.getKind() == ObjectKind.TABLE }.each { generate(it, dir) }
}


def generate(table, dir) {
    def className = javaName(table.getName(), true).toString().substring(2) + "Entity"
    def fields = calcFields(table)
    packageName = getPackageName(dir)
    // solve the garbled problem
    new File(dir, className + ".java").withPrintWriter("utf-8") { out -> generate(out, className, fields, table) }
}


// Get the folder path of the package
def getPackageName(dir) {
    return dir.toString().replaceAll("\\\\", ".").replaceAll("/", ".").replaceAll("^.*src(\\.main\\.java\\.)?", "") + ";"
}

def generate(out, className, fields, table) {
    out.println "package $packageName"
    out.println ""
    out.println "import javax.persistence.*;"
    out.println "import lombok.*;"

    Set types = new HashSet()

    fields.each() {
        types.add(it.type)
    }

    if (types.contains("BigDecimal")) {
        out.println "import java.math.BigDecimal;"
    }

    if (types.contains("LocalDateTime")) {
        out.println "import java.util.LocalDateTime;"
    }

    out.println ""
    out.println "@Entity"
    out.println "@Table (name = \"" + table.getName() + "\")"
    out.println "@NoArgsConstructor(access = AccessLevel.PROTECTED)"
    out.println "@Getter"
    out.println "public class $className {"
    out.println ""
    fields.each() {
        // output comment
        if (isNotEmpty(it.commoent)) {
            out.println "\t/**${it.commoent.toString()}*/"
        }

        if (it.annos != "") out.println "   ${it.annos}"
        // output member variable
        out.println "\tprivate ${it.type} ${it.name};\n"
    }
    out.println ""
    out.println "}"
}

def calcFields(table) {
    DasUtil.getColumns(table).reduce([]) { fields, col ->
        def spec = Case.LOWER.apply(col.getDataType().getSpecification())

        def typeStr = typeMapping.find { p, t -> p.matcher(spec).find() }.value
        def comm = [
                colName : col.getName(),
//                name    : changeStyle(fileName(col.getName(), false), true),
                name : javaName(col.getName(), false),
                type    : typeStr,
                commoent: col.getComment(),
                annos   : "\t@Column(name = \"" + col.getName() + "\")"]
        if ("CODE".equals(col.getName())){
            comm.annos = "\t@Id\n"
            //Need to increase the primary key
            comm.annos += "\t@GeneratedValue(strategy = GenerationType.IDENTITY)\n"
            comm.annos += "\t@Column(name = \"" + col.getName() + "\")"
        }
        if ("reg_dt".equals(Case.LOWER.apply(col.getName()))){
            comm.annos += "\n\t@CreatedDate"
        }
        if ("upt_dt".equals(Case.LOWER.apply(col.getName()))){
            comm.annos += "\n\t@UpdateDate"
        }
        fields += [comm]
    }
}

def javaName(str, capitalize) {
  def s = com.intellij.psi.codeStyle.NameUtil.splitNameIntoWords(str)
    .collect { Case.LOWER.apply(it).capitalize() }
    .join("")
  capitalize || s.length() == 1? s : Case.LOWER.apply(s[0]) + s[1..-1]
}

def isNotEmpty(content) {
    return content != null && content.toString().trim().length() > 0
}

 

다른 방법

JPA Persistence > Generate Persistence Mapping > By Database Schema 를 이용해 한번에 벌크로 생성해줄 수도 있지만 커스텀(데이터 타입, 어노테이션 등)이 자유롭지 않다는 단점이 있습니다.