프로바이더 설정

본 장에서는 JEUS의 기본 프로바이더인 EclipseLink에 대한 설정을 설명한다. 이러한 설정은 JPA 스펙에서 정의되지 않는 기능을 구현하기 위해 필요한 부분으로, 각 애플리케이션에 맞게 정확하게 설정되어야 한다.

1. 데이터베이스 설정

사용 환경, 데이터베이스 타입에 따른 설정과 자동으로 데이터베이스 스키마를 생성하는 설정에 대해 설명한다.

1.1. 사용 환경별 설정

사용 환경에 따라 데이터베이스의 설정 방법이 달라진다.

Jakarta EE 환경

Jakarta EE 환경(또는 모드)은 JEUS의 Managed Server(이하 MS) 위에서 웹 컨테이너, EJB 컨테이너, 애플리케이션 클라이언트 컨테이너를 의미한다.

좀 더 정확하게는 각 컨테이너에서 컨트롤하는 Thread를 의미한다. 예를 들어 웹 엔진에 설정하는 Web Thread Pool의 Thread이다. 만약 애플리케이션이 직접 생성한 Thread Pool의 Thread처럼 컨테이너가 관리하지 않는 Thread 상에서는 Java SE 환경과 똑같다.

사용할 데이터베이스 대상에 대한 설정은 persistence.xml Descriptor에 설정한다. 사용할 트랜잭션의 종류에 따라서 <jta-data-source>와 <non-jta-data-source> 값을 설정한다.

  • 글로벌 트랜잭션을 사용하는 경우

    • <transaction-type>의 값을 'JTA’로 설정한다.

    • <jta-data-source>에 해당 데이터소스의 JNDI 이름을 설정한다.

  • 로컬 트랜잭션을 사용하는 경우

    • <transaction-type>의 값을 'RESOURCE_LOCAL’로 설정한다.

    • <non-jta-data-source>에 해당 데이터소스의 JNDI 이름을 설정한다.

Jakarta EE 모드에서 데이터베이스 설정 예
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="em" transaction-type="JTA">
    <jta-data-source>jdbc/MyDB</jta-data-source>
  </persistence-unit>
</persistence>
  1. Jakarta EE 환경에서는 <transaction-type> 값을 지정하지 않을 경우 기본적으로 JTA 트랜잭션으로 설정한다.

  2. JEUS에서 DB 데이터소스를 설정하는 방법은 JEUS Server 안내서의 DB Connection Pool과 JDBC를 참고한다.

Java SE 환경

Java SE 환경(또는 모드)은 Jakarta EE 컨테이너에서 사용하지 않고 Java Standalone 클라이언트와 같은 환경에서 사용하는 경우를 말한다. 이때는 로컬 트랜잭션만 사용할 수 있으며, 사용되는 데이터베이스의 JDBC 설정을 프로퍼티로 설정해야 한다.

다음의 예제와 같이 <transaction-type>의 값을 'RESOURCE_LOCAL’로 설정한다.

Java SE 모드에서 데이터베이스 설정 예
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="em" transaction-type="JTA">
    <jta-data-source>jdbc/MyDB</jta-data-source>
  </persistence-unit>
</persistence>

다음은 프로퍼티 값에 대한 설명이다.

프로퍼티 값 설명

eclipselink.jdbc.driver

대상 데이터베이스의 JDBC 드라이버 클래스 이름이다.

eclipselink.jdbc.url

대상 데이터베이스의 JDBC URL이다.

eclipselink.jdbc.user

대상 데이터베이스의 사용자명이다.

eclipselink.jdbc.password

대상 데이터베이스의 패스워드이다.

1.2. 데이터베이스 타입 설정

기본적으로 해당 데이터베이스 타입을 JDBC 커넥션 정보를 통해 자동으로 감지한다. 자동 감지 기능이 제대로 동작하지 않거나, 별도의 다른 데이터베이스를 사용하는 경우라면 'eclipselink.target-database' 프로퍼티를 설정할 수 있다.

데이터베이스 타입은 JDBC 드라이버의 DatabaseMetaData.getDatabaseProductName()을 사용하여, 데이터베이스 벤더 이름을 regular expression으로 비교하는 방식을 사용한다.

데이터베이스 타입 설정 예
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="em">
    <jta-data-source>jdbc/MyDB</jta-data-source>
    <properties>
      <property name="eclipselink.target-database" value="DB2"/>
    </properties>
  </persistence-unit>
</persistence>

다음은 지원되는 데이터베이스 타입 값에 대한 설명이다.

설명

Auto

자동 감지(기본값)

Cloudscape

Cloudscape DBMS

DB2

IBM DB2 DBMS

DB2Mainframe

IBM DB2 Mainframe DBMS

Derby

Apache Derby DBMS

HSQL

HSQL DBMS

JavaDB

JavaDB DBMS

MySQL4

MySQL DBMS

Oracle

Oracle DBMS

PostreSQL

PostreSQL DBMS

SQLServer

Microsoft SQLServer DBMS

Sybase

Sybase DBMS

Customized class name

기본적으로 지원되지 않는 DBMS를 추가할 때 사용한다.

그 외

그 외의 DB에 대해서는 eclipselink의 Persistence Property Extensions Reference 페이지에서 target-database 부분을 참고한다.

기본적으로 지원되지 않는 DBMS의 경우 별도로 DBMS 지원 기능을 구현하여 사용할 수 있다. 이때는 해당 클래스 이름을 지정한다. 이에 대한 자세한 내용은 본 안내서의 참고 자료를 참고한다.

1.3. 스키마 자동 생성 설정

자동으로 DB 스키마를 생성하는 기능을 사용하는 경우 설정한다. 이를 사용하면 애플리케이션을 deploy할 때 DB 테이블 및 제약 사항(Constraints)을 자동으로 생성한다.

스키마 자동 생성 설정 예
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="em">
    <jta-data-source>jdbc/MyDB</jta-data-source>
    <properties>
      ...
      <property name="eclipselink.ddl-generation" value="create-tables" />
      ...
    </properties>
  </persistence-unit>
</persistence>

관련된 프로퍼티 설정은 다음과 같다.

항목 설명

eclipselink.ddl-generation

스키마 DDL(Data Descriptor Language)을 어떤식으로 생성할지 설정한다.

  • none : 아무것도 하지 않는다. (기본값)

  • create-tables : 존재하지 않는 테이블을 생성하며, 기존 테이블은 그대로 남겨둔다.

  • drop-and-create-tables : 기존에 존재하는 테이블을 삭제하고 다시 생성한다.

  • create-or-extend-tables : 테이블을 생성하되, 기존에 존재하는 테이블이 있으면 없는 column만 추가한다.

DDL을 생성할 때 기본적으로 다음과 같이 Java 타입을 해당 데이터베이스 SQL 타입에 맞게 생성한다.

Java Type Derby, JavaDB, Cloudscape Oracle DB2 Sybase SQLServer MySQL

boolean, Boolean

SMALLINT

NUMBER(1)

SMALLINT

BIT

BIT

TINYINT(1)

int, Integer

INTEGER

NUMBER(10)

INTEGER

INTEGER

INTEGER

INTEGER

long, Long

BIGINT

NUMBER(19)

INTEGER

NUMERIC(19)

NUMERIC(19)

BIGINT

float, Float

FLOAT

NUMERIC(19,4)

FLOAT

FLOAT(16)

FLOAT(16)

FLOAT

double, Double

FLOAT

NUMERIC(19,4)

FLOAT

FLOAT(32)

FLOAT(32)

DOUBLE

short, Short

SMALLINT

NUMBER(5)

SMALLINT

SMALLINT

SMALLINT

SMALLINT

byte, Byte

SMALLINT

NUMBER(3)

SMALLINT

SMALLINT

SMALLINT

SMALLINT

java.lang.Number

DECIMAL

NUMBER(38)

DECIMAL(15)

NUMERIC(38)

NUMERIC(28)

DECIMAL(38)

java.math.BigInteger

BIGINT

NUMBER(38)

BIGINT

NUMERIC(38)

NUMERIC(28)

BIGINT

java.math.BigDecimal

DECIMAL

NUMBER(38)

DECIMAL(15)

NUMERIC(38)

NUMERIC(28)

DECIMAL(38)

java.lang.String

VARCHAR(255)

VARCHAR(255)

VARCHAR(255)

VARCHAR(255)

VARCHAR(255)

VARCHAR(255)

char, Character

CHAR(1)

CHAR(1)

CHAR(1)

CHAR(1)

CHAR(1)

CHAR(1)

byte[], Byte[], java.sql.Blob

BLOB(64000)

LONG RAW

BLOB(64000)

TEXT

TEXT

TEXT(64000)

char[], Character[], java.sql.Clob

CLOB(64000)

LONG

CLOB(64000)

TEXT

TEXT

TEXT(64000)

java.sql.Date

DATE

DATE

DATE

DATETIME

DATETIME

DATE

java.sql.Time

TIME

DATE

TIME

DATETIME

DATETIME

TIME

java.sql.Timestamp

TIMESTAMP

DATE

TIMESTAMP

DATETIME

DATETIME

DATETIME

2. Caching

JPA에서는 기본적으로 Persistence Context라고 하는 1st-level Caching을 지원하고 있다. 하지만, 일반적으로 Persistence Context는 트랜잭션별로 새로 생성되기 때문에(Extended Persistence Context는 이에 해당하지 않음) 트랜잭션 간에 Caching을 지원하지 않는다. 이를 보완하기 위해 Eclipse Link 에서는 2nd-level Caching 기능을 제공한다.

2nd-level Caching은 EntityManagerFactory 레벨에서 지원되기 때문에, 동일한 EntityManagerFactory에서 생성된 모든 EntityManager의 경우 이 공유 Cache를 사용하게 된다. 즉, Persistence Context에 없는 Entity를 가져올 때 2nd-level Caching을 참고하여 존재하는 경우에 이를 가져온다. 따라서 반복적인 Read 작업의 경우 성능 향상을 가져오게 된다.

Caching 방식 설정 예
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="em">
    <jta-data-source>jdbc/MyDB</jta-data-source>
    <properties>
      ...
      <property name="eclipselink.ddl-generation" value="create-tables" />
      <property name="eclipselink.cache.type.default" value="NONE" />
      <property name="eclipselink.cache.size.default" value="999" />
      <property name="eclipselink.cache.shared.default" value="false" />
      ...
    </properties>
  </persistence-unit>
</persistence>

다음은 Caching에 관련된 옵션에 대한 설명이다.

항목 설명

eclipselink.cache.type.default

Caching 방식을 설정한다.

아래의 옵션들 이외의 옵션이나 옵션에 대한 자세한 설정은 EclipseLink User Guide의 Cache Type and Size 항목을 참고한다.

  • Full : 객체를 Hard reference로 caching한다. 따라서 Entity가 삭제되기 전까지 항상 Cache에 존재하게 된다.

  • Weak : 객체를 Weak reference로 caching한다. Garbage Collection(GC)이 되면 사라진다.

  • Soft : Weak와 유사하지만, 메모리가 부족할 때만 객체를 삭제한다. (기본값)

  • NONE : 객체를 Cache에 저장하지 않는다. 사용을 권장하지 않으며 Caching 기능을 사용하고 싶지 않다면, eclipselink.cache.shared.default 또는 eclipselink.cache.shared.<ENTITY> 프로퍼티 설정을 권장한다.

eclipselink.cache.size.default

Cache에 저장될 최대 객체수를 설정한다. (기본값: 1000)

eclipselink.cache.shared.default

공유 Cache를 사용할지 여부를 설정한다.

  • true : 객체가 공유 Cache에 저장된다. 모든 EntityManager는 Caching을 사용하게 된다. (기본값)

  • false : 객체가 공유 Cache에 저장되지 않는다. 따라서, EntityManager별로 Cache를 공유하지 않는다. 이를 사용하면 2nd-level Caching을 하지 않는 효과가 있다.

eclipselink.cache.type.<ENTITY>

Entity별로 Caching을 하는 방식을 지정한다.

<ENTITY>는 Entity 이름 또는 fully-qualified 클래스 이름이 될 수 있다. 해당 Entity와 관계를 가지는 모든 Entity는 같은 설정을 가져야 한다. eclipselink.cache.type.default의 값 설명과 동일하다.

eclipselink.cache.size.<ENTITY>

Entity별로 Cache 사이즈를 지정한다.

<ENTITY>는 Entity 이름 또는 fully-qualified 클래스 이름이 될 수 있다. eclipselink.cache.size.default의 값 설명과 동일하다.

eclipselink.cache.shared.<ENTITY>

Entity별로 공유 Cache를 사용할지를 지정한다.

<ENTITY>는 Entity 이름 또는 fully-qualified 클래스 이름이 될 수 있다. 해당 Entity와 관계를 가지는 모든 Entity는 동일한 설정을 가져야 한다. eclipselink.cache.shared.default의 값 설명과 동일하다.

2nd-level Caching이 사용될 때 주의할 것은 외부 애플리케이션에 의해 또는 직접 데이터베이스의 데이터를 변경하는 경우 해당 내용이 Caching에 반영되지 않는다는 점이다. 이런 경우 데이터베이스의 최신 값이 아닌 Caching된 값이 리턴되기 때문에 애플리케이션에 이를 고려해야 한다.

Caching 옵션을 애플리케이션 환경을 고려하여 적절히 설정하거나, EntityManager.refresh(), eclipselink.refresh Query 힌트 또는 locking(pessimistic/optimistic) 등을 사용하여 이런 문제를 피할 수 있다.

3. Query 힌트

Query 힌트는 Query 객체를 사용할 때 프로바이더에서 제공하는 기능을 사용하도록 한다.

다음 예제와 같이 Query를 실행할 때 설정할 수도 있고, Named Query를 사용하는 경우 @QueryHint Annotation을 사용하여 지정할 수도 있다.

Query 힌트 사용 예제
List employees = em.createQuery("SELECT e FROM Employee e WHERE e.name = :name")
      .setParameter("name", name)
      .setHint("eclipselink.refresh", true)
      .getResultList();

제공하는 Query 힌트는 다음과 같다.

항목 설명

eclipselink.pessimistic-lock

SELECT할 때 Pessimistic Locking을 사용할지 여부를 설정한다.

  • NoLock : 사용하지 않는다. (기본값)

  • Lock : SELECT …​ FOR UPDATE 문을 사용해 Locking을 한다.

  • NoLockWait : SELECT …​ FOR UPDATE NO WAIT 문을 사용해 Locking을 한다.

eclipselink.refresh

데이터베이스에서 최신 값을 가져와 Caching을 업데이트할지 여부를 설정한다.

  • true : 최신 값을 가져오고 Caching을 업데이트한다.

  • false : Cache에 있는 값을 사용한다. (기본값)

4. Logging 설정

좀 더 자세한 로그를 보고 싶다면 Logging 레벨을 설정할 수 있다.

기본적으로 Logging 레벨은 JEUS 서버에 전체적으로 적용되는 레벨(기본적으로 INFO)을 따르게 되지만, 이를 Persistence Unit별로 변경할 경우 eclipselink.logging.level 프로퍼티로 설정할 수 있다.

Logger의 경우 Jakarta EE 모드에서는 기본적으로 JEUS에서 제공되는 Logger(JEUS Logger)를 사용하게 되며, Java SE 모드에서는 standard output으로 출력되는 DefaultLogger를 사용하게 된다. 이를 변경하려면 eclipselink.logging.logger 프로퍼티로 설정할 수 있다.

Logging 설정 예
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="em">
    <jta-data-source>jdbc/MyDB</jta-data-source>
    <properties>
      ...
      <property name="eclipselink.logging.level" value="FINE"/>
      <property name="eclipselink.logging.logger" value="DefaultLogger"/>
      ...
    </properties>
  </persistence-unit>
</persistence>

다음은 설정에 대한 자세한 설명이다.

항목 설명

eclipselink.logging.level

Logging 레벨을 지정한다.

  • OFF : Logging을 하지 않는다.

  • SEVERE

  • WARNING

  • INFO (기본값)

  • CONFIG

  • FINE : SQL 관련 정보를 조회하려면 이 레벨로 설정한다.

  • FINER

  • FINEST

eclipselink.logging.logger

사용할 Logger를 지정한다.

  • JEUSLogger : JEUS에서 제공되는 Logger이다. (Jakarta EE 모드인 경우 기본값)

  • DefaultLogger : 기본 standard output Logger이다. (Java SE 모드인 경우 기본값)

  • JavaLogger : java.util.logging Logger이다.

  • Custom class name : 별도의 Logger를 구현한 경우 지정한다.

EclipseLink에 대한 자세한 설정은 EclipseLink JPA 사용자 안내서를 참고한다.