IntelliJ에서 Java만으로 JPA 프로젝트 CRUD 시작하기 (Ver. Maven)

조현성·2020년 1월 31일
2

Java Programming

목록 보기
1/1
post-thumbnail

회사내에서 스터디 붐(?)이 발생하며 기술스택 변경에 대한 니즈가 강하게 일어났다. 특히 우리는 Java를 사용 또는 연동하는 거의 모든것들(?)에 대해서 SpringBoot와 JPA(Java Persistence API)기반한 기술 스택을 가져가기로 결정했다. 웹개발 쪽에서는 당연지사 SpringBoot와 병행하여 사용해야 겠으나, 우리 IPCC(IP Contact Center)쪽 같은 경우 생 자바로 개발된 엘리먼트와 데몬 프로그램을 대체하기 위해서는 Maven이나 Gradle로 개발되는 JPA 자바 프로젝트 학습이 필요 했다.

본 포스팅에서는 우아한형제들 김영한님의 인프런 강좌인 <자바 ORM 표준 JPA 프로그래밍 – 기본편>을 참조하여 IntelliJ 개발도구를 이용한 Maven 기반 자바 프로젝트로 H2, MS-SQL, PostgreSQL, Oracle, Tibero 5가지 DBMS에 대한 의존성 주입 및 persistence.xml 파일 설정으로 JPA를 사용해 본다.

로컬 환경의 자바 버전은 1.8.0.221로 진행 했고, 각 DBMS별 의존성 및 외부라이브러리 참조 파일은 최대한 높은 버전을 사용 했다. 다음 절차대로 프로젝트를 생성 하고 각 경로에 맞는 파일 환경을 갖춘다면 위에 언급된 DBMS에 모두 작업을 할 수 있다.

1. Maven 프로젝트 생성
IntelliJ 에서 신규 프로젝트를 생성 하고, Maven을 선택 한 후 [Next] 버튼을 클릭 한다.

GroupId 란에는 회사 도메인 주소 역순 또는 본인이 소유하고 있는 도메인 주소 역순을 (그것도 아니면 원하는 도메인 주소 역순…)을 작성 하고, ArtifactId란에는 프로젝트명으로 사용할 이름을 작성 후 [Next] 버튼을 클릭 한다.

신규 프로젝트가 생성되면 아래 그림과 같이 프로젝트에 필요한 파일을 자동으로 import 시킬 것인지 묻는 알람창이 나오는데 이때 [Enable Auto-import]를 눌러서 자동으로 import 되도록 설정 한다.

생성 완료된 프로젝트 구조를 보면, src\main\java 구조로 되어 있고, pom.xml 에는 프로젝트 관련정보만 작성되어 있다.

2. 패키지 생성 및 lib 폴더 추가
java 디렉토리에서 우클릭 하여 앞에서 설정한 GroupId 대로 패키지를 생성한다.


src 경로 밑에 필요한 라이브러리 jar 파일을 모아놓을 ‘lib’ 폴더를 생성 하면, 프로젝트 구조는 다음과 같다.

3. 의존성 주입 및 jdbc 라이브러리 jar 추가
pom.xml 파일에 다음과 같이 의존성을 주입 한다.

  • Java 1.8을 사용하기 위한 Build 설정
  • JPA 하이버네이트 사용을 위한 의존성 주입
  • H2 데이터베이스 사용을 위한 의존성 주입
  • MS-SQL 데이터베이스 사용을 위한 의존성 주입
  • PostgreSQL 데이터베이스 사용을 위한 의존성 주입
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.day1st</groupId>
    <artifactId>maven-jpa</artifactId>
    <version>1.0-SNAPSHOT</version>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- JPA 하이버네이트 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.3.10.Final</version>
        </dependency>

        <!-- H2 데이터베이스 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.199</version>
        </dependency>

        <!-- MS-SQL 데이터베이스 -->
        <dependency>
            <groupId>com.microsoft.sqlserver</groupId>
            <artifactId>mssql-jdbc</artifactId>
            <version>7.4.1.jre8</version>
        </dependency>

        <!-- PostgreSQL 데이터베이스 -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.2.8</version>
        </dependency>
    </dependencies>
</project>

mvnrepository(https://mvnrepository.com) 에서 제공되는 의존성은 모두 주입 하였고, Oracle 과 Tibero는 별도 jar 파일을 구해서 미리 생성해둔 ‘lib’ 폴더에 옮겨 넣으면 프로젝트 구조는 다음과 같다.

Windows 기준, [Ctrl]+[Alt]+[Shift]+[S] 단축키를 이용해 Project Structure 메뉴에어스 [Libraries] 탭으로 이동하여 ‘lib’ 폴더의 jar 경로를 추가 해준다.


다음과 같이 추가가 완료 되었다면 [Apply] 후 [OK] 버튼을 클릭 한다.

4. META-INF 디렉토리와 persistence.xml 파일 생성
JPA를 사용하기 위해서는 정해진 경로의 META-INF 디렉토리밑에 persistence.xml 파일이 존재해야 한다. resources 경로 밑에 META-INF 디렉토리를 생성 하고, 그 밑에 persistence.xml 파일을 생성 후 다음 DBMS 사용을 위한 정보들을 입력 한다.

※ 아래 설정 정보들은 H2 데이터베이스는 로컬에 설치 되어 있다고 가정 하였고, MS-SQL, Oracle, Tibero, Postgres 의 경우 192.168.111.222 원격 서버에 ‘study’ 라는 데이터베이스 이름과, user id / pw 가 모두 ‘study’로 생성 되었다고 간주 한다.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="study">
        <properties>
            <!-- H2 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/C:/Users/evo/Database/h2/study"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

            <!-- MS-SQL 필수 속성 -->
            <!--<property name="javax.persistence.jdbc.driver" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value="study"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:sqlserver://192.168.111.222:1433;databaseName=study"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>-->

            <!-- Oracle 필수 속성 -->
            <!--<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
            <property name="javax.persistence.jdbc.user" value="study"/>
            <property name="javax.persistence.jdbc.password" value="study"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@192.168.111.222:1521:orcl"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>-->

            <!-- Tibero 필수 속성 -->
            <!--<property name="javax.persistence.jdbc.driver" value="com.tmax.tibero.jdbc.TbDriver"/>
            <property name="javax.persistence.jdbc.user" value="study"/>
            <property name="javax.persistence.jdbc.password" value="study"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:tibero:this:@192.168.111.222:8629:tibero"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>-->

            <!-- PostgreSQL 필수 속성 -->
            <!--<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
            <property name="javax.persistence.jdbc.user" value="postgres"/>
            <property name="javax.persistence.jdbc.password" value="study"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://192.168.111.222:5432/postgres"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL95Dialect"/>-->

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <property name="hibernate.jdbc.batch_size" value="10"/>
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

5. 테스트를 위한 Agent 엔티티 생성 및 main 함수
Agent 엔티티 객체를 생성 후 [Alt] + [Insert] 키를 사용하여 Getter/Setter를 자동 생성 해준다.

package com.day1st;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
 
@Entity
public class Agent {
    @Id
    @GeneratedValue
    private Long id;
 
    private String name;
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
}

CRUD를 테스트 해볼 main 메서드 클래스를 생성 하고 EntityManagerFactory, EntityManager, EntityTransaction 생성부터 트랜잭션 커밋 후 닫는 코드 까지 뼈대를 만들어 둔다. 이때 주의 할 점은 Main 클래스에서 createEntityManagerFactory 할 때 작성되는 persistenceUnitName 과 persistence.xml 파일의 <persistence-unit name= > 값이 같아야 한다는 것이다.

package com.day1st;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("study");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
 
 
            //트랜잭션 커밋!
            tx.commit();
        }catch(Exception e){
            tx.rollback();
        }finally{
            em.close();
        }
        emf.close();
    }
}  

이제 try 구문안에 아래와 같이 코드를 넣고 CRUD 테스트를 진행 해본다. 아래 테스트에서는 Insert 할 때만 persistence.xml 파일의 “hibernate.hbm2ddl.auto” 옵션을 create 로 두고, 나머지는 옵션을 none 으로 변경 후 테스트 한다.

  • INSERT 하기

package com.day1st;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("study");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            Agent agent = new Agent();
            // ID는 자동 생성되도록 했으므로 이름만 SET 해본다.
            agent.setName("evohjo");
 
            // 영속화
            em.persist(agent);
 
            //트랜잭션 커밋!
            tx.commit();
        }catch(Exception e){
            tx.rollback();
        }finally{
            em.close();
        }
        emf.close();
    }
}  
  • SELECT 하기

package com.day1st;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("study");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            // ID 값이 1인 Agent SELECT
            Agent findAgent = em.find(Agent.class, 1L);
 
            // 정보 출력
            System.out.println("Id : " + findAgent.getId());
            System.out.println("Name : " + findAgent.getName());
 
            //트랜잭션 커밋!
            tx.commit();
        }catch(Exception e){
            tx.rollback();
        }finally{
            em.close();
        }
        emf.close();
    }
}  
  • UPDATE 하기
package com.day1st;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("study");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            // ID 값이 1인 Agent SELECT
            Agent findAgent = em.find(Agent.class, 1L);
 
            // 이름을 Hello 로 수정
            findAgent.setName("Hello");
 
            //트랜잭션 커밋!
            tx.commit();
        }catch(Exception e){
            tx.rollback();
        }finally{
            em.close();
        }
        emf.close();
    }
}  
  • DELETE 하기
package com.day1st;
 
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
 
public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("study");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        tx.begin();
        try{
            // ID 값이 1인 Agent SELECT
            Agent findAgent = em.find(Agent.class, 1L);
 
            // 삭제
            em.remove(findAgent);
 
            //트랜잭션 커밋!
            tx.commit();
        }catch(Exception e){
            tx.rollback();
        }finally{
            em.close();
        }
        emf.close();
    }
}

이상으로 Maven 기반의 생 자바 JPA를 CRUD 해보았다.

본 포스팅에서는 영속성컨텍스트 및 persistence.xml 파일의 옵션 등 다양한 주제에 대해서는 다루지 않았지만 위 환경정보를 사용해 여러 DBMS를 접속하여 DBMS별 서로 다르게 JPA에서 생성해주는 쿼리를 확인해 볼 수는 있을 것이다. 또한, DBeaver(https://dbeaver.io)를 사용하면 포스팅에 언급된 5개 DBMS를 모두 붙여볼 수 있으니 참고 하도록 하자.


profile
올바른 내공의 축적

0개의 댓글