반응형
Hibernate API에서 사용될 세션 및 트랜잭션 프로퍼티를 설정하는 방법에 대해서 살펴본다.
Hibernate의 세션 설정 방법 및 프로퍼티 설정 방법
Hibernate API를 사용하는 기본 코드는 아래와 같은 형태를 띄고 있다.
코드는 크게
Hibernate Session 생성 방법
Session은 데이터베이스 세션을 의미하는 것으로서, Session이 사용할 데이터베이스 커넥션을 구하는 방법은 다음과 같이 3가지가 존재한다.
프로퍼티 정보 명시하기
커넥션 정보는 프로퍼티를 통해서 명시할 수 있는데, 프로퍼티는 4가지 방법으로 지정할 수 있다. Hibernate는 다음의 순서대로 프로퍼티 정보를 읽어온다.
위의 네 가지 방법 중에서 두번째와 네번째는 파일을 클래스패스 루트에 위치시키면 다음의 코드를 통해서 Hibernate가 설정 파일로부터 프로퍼티를 읽어온다.
하지만, 첫번째 방법을 사용하고 싶다면 아래와 같이 직접 코드에서 Properties 객체를 생성한 뒤 Configuration 객체에 전달해주어야 한다.
네 가지 방법 중 어떤 방법으로 사용하더라도 Hibernate가 사용하는 프로퍼티의 이름과 값의 의미는 동일하므로, 본 글에서는 XML 파일 포맷인 hibernate.cfg.xml 파일에 프로퍼티 정보를 명시하는 방법을 사용해서 커넥션 정보를 명시하는 형태로 예제를 보여줄 것이다.
Sessin 설정 방법: JNDI 설정/커넥션 풀/직접 커넥션 제공
앞서 말했듯이 Hibernate Session이 사용할 데이터베이스 커넥션을 JNDI나 Hibernate의 커넥션 풀로부터 얻어오거나 또는 사용자가 직접 제공한 커넥션을 사용할 수도 있다.
JNDI 설정
Hibernate가 JNDI에 바인딩된 DataSource로부터 데이터베이스 커네션을 구하도록 설정하려면 다음과 같은 프로퍼티를 사용하면 된다.
예를 들어, JNDI에 등록된 DataSource의 이름이 "hibernate" 라면 다음과 같이 connection.datasource 프로퍼티 값을 설정해주면 된다. (위 표에 있는 나머지 프로퍼티들은 대부분의 WAS에서 설정하지 않아도 문제가 되지 않는다.)
위 프로퍼티에서 DataSource외에 나머지 프로퍼티에 대해서 'SQL Dialect와 트랜잭션 전략 설정' 부분에서 설명할 것이므로 아직까진 신경쓰지 말기 바란다.
간단하게 톰캣의 예를 들어, 데이터 소스 설정 예제를 살펴보도록 하겠다. 참고로, 여기서 보여주는 예제는 지난 1회 글 'Hibernate를 이용한 ORM 1 - 퀵 스타트'에서 사용한 예제에서 설정 파일부분만 변경한 것이다.
먼저 톰캣에 웹 어플리케이션에서 사용할 DataSource에 대한 JNDI 설정을 추가해야 한다. 이 설정은 [톰캣]/conf/server.xml 파일에 추가하면 되며, 아래와 같은 형태의 코드를 사용하면 된다. (톰캣에서 DataSource를 추가하는 방법에 대한 자세한 내용은 톰캣 사이트인 http://jakarta.apache.org/tomcat/을 참고하기 바란다.)
위 코드에서는 JNDI에 등록될 DataSource의 이름을 "jdbc/hibernate"로 지정하였는데, 이는 실제로 "java:comp/env/" 콘텍스트에 추가되므로 설정한 DataSource의 완전한 JNDI 이름은 "java:comp/env/jdbc/hibernate"가 된다. 따라서, Hibernate의 설정 파일에 아래와 같이 hibernate.connection.datasource 프로퍼티의 값을 주면 된다.
어플리케이션 서버(톰캣)에 DataSource를 JNDI에 등록하고, JNDI를 사용하도록 Hibernate의 프로퍼티를 설정하면 모든 게 완료된다. 소스 코드는 전혀 변경할 필요가 없이 이 두가지만 변경해주면 1회에 작성했던 예제를 실행할 수 있을 것이다.
커넥션 풀 설정
Hibernate는 자체적으로 커넥션 풀 기능을 제공하고 있는데, Hibernate Session이 커넥션 풀로부터 필요한 데이터베이스 커넥션을 구하도록 설정할 수 있다. 기본적인 설정 방법은 다음과 같다.
위의 설정 내용을 보면 알겠지만, Hibernate Session이 Hibernate가 제공하는 커넥션 풀을 사용하도록 설정하려면 다음의 네 가지 기본 프로퍼티를 요구한다.
DBCP 관련 프로퍼티
위의 모든 프로퍼티를 지정할 필요는 없으며, hibernate.dbcp. 로 시작하는 프로퍼티가 존재하면 Hibernate는 DBCP를 커넥션 풀 모듈로 사용하게 된다.
커넥션 Session에 직접 전달
앞서 두 가지 방법, 즉 JNDI를 사용하는 방법과 커넥션 풀을 사용하는 방법은 Hibernate의 프로퍼티로 설정할 수 있었다. 그런데 부득이한 이유로 JNDI나 커넥션 풀을 사용할 수 없는 경우도 있을 것이다. 예를 들어, 기존 커넥션 관련 모듈이 있어서 Hibernate도 이 모듈에서 제공하는 커넥션을 사용해야 하는 경우가 발생할 수 있다.
이런 경우에는 커넥션 관련된 Hibernate 프로퍼티에서 설정할 값이 없으며, 다음과 같이 SessionFactory.openSession(Connection conn) 메소드를 호출해서 Session 객체를 생성하면 된다.
직접 커넥션을 Session에 전달할 때 주의할 점은, 하나의 JDBC 커넥션에 대해서 동시에 두 개의 열린 Session을 생성해서는 안 된다는 점이다. 즉, 다음과 같은 코드를 작성하지 않도록 주의해야 한다.
SQL Dialect와 트랜잭션 속성/처리 클래스 설정
Hibernate는 DBMS에 따라서 최적화된 기능을 제공할 수 있으며, 또한 사용할 어플리케이션 서버에 알맞은 트랜잭션 기능을 제공할 수 있다. DBMS에 최적화된 기능을 제공하기 위해 사용되는 것이 SQL Dialect이며, hibernate.trasaction.manager_lookup_class 프로퍼티를 통해서 트랜잭션 처리 클래스를 설정할 수 있다.
SQL Dialect
Hibernate는 특정 DBMS가 제공하는 기능을 사용할 수 있는 기능을 제공하며, Dialect 프로퍼티를 사용해서 이 기능을 사용할 수 있다. 예를 들어, Hibernate는 오라클를 사용할 때는 오라클에 최적화되도록 기능을 수행하며 MySQL을 사용하는 경우에는 MySQL에 최적화되도록 기능을 수행할 수 있다. 예를 들어, 오라클에 알맞은 Dialect를 설정하면, Hibernate는 시퀀스와 같이 DBMS에 특징적인 기능을 개발자가 직접 코딩하지 않고도 사용할 수 있게 된다.
hibernate.dialect 프로퍼티 값을 명시하면 SQL Dialect를 설정할 수 있는데, 각 DBMS에 따라 다음 표와 같이 프로퍼티값을 명시하면 된다.
트랜잭션 속성 및 처리 클래스 설정
Hibernate의 Transaction 객체를 사용하기 위해서는 hibernate.transaction.factory_class 프로퍼티 속성을 설정해야 한다. 이 속성을 통해서 사용할 Transaction 구현체를 명시하게 된다. Hibernate는 기본적으로 두 가지 Transaction 구현체를 제공하고 있으며, 이 두 구현체는 다음과 같다.
JTA 환경에서 변경가능한 데이터를 JVM 레벨에서 캐싱하기 위해서는, JTA TransactionManager를 구하기 위한 전력을 명시해야 한다. JTA TransactionManager를 구할 클래스를 명시할 때에는 hibernate.transaction.manager_lookup_class 프로퍼티의 값을 WAS에 따라 알맞게 명시하면 된다. 아래표는 WAS에 따라 사용할 프로퍼티 값 목록이다.
SessionFactory JNDI 등록
hibernate.session_factory_name 프로퍼티를 사용해서 JNDI 이름공간에 SessionFactory를 등록할 수 있다. hibernate.session_factory_name 프로퍼티의 값은 SessionFactory를 JNDI에 등록할 때 사용될 이름이 된다. 예를 들어, java:comp/env/hibernate/SessionFactory와 같은 이름을 사용하게 된다.
hibernate.session_factory_name 프로퍼티를 생략하면 SessionFactory를 JNDI에 등록하지 않는다. Tomcat과 같이 읽기전용 JNDI 구현체를 사용하는 서버에서는 hibernate.session_factory_name 프로퍼티 값을 설정하지 않는 것이 좋다.
hibernate.jndi.url 프로퍼티와 hibernate.jndi.class 프로터리를 사용해서 SessionFactory를 JNDI에 등록할 때 사용할 InitialContext를 명시할 수 있다. 이 속성값을 명시하지 않으면 기본 InitialContext가 사용된다.
다음 글에서는
이번 2회에서는 Hibernate가 사용할 데이터베이스 세션을 설정하는 세 가지 방법, 즉 JNDI를 이용하는 방법, 커넥션 풀을 사용하는 방법, 그리고 직접 코드에서 커넥션을 제공하는 방법에 대해서 살펴보았다. 그리고 DBMS의 기능을 활용할 수 있는 SQL Dialect 설정 방법과 WAS 서버에 따라 달라지는 JNDI 트랜잭션 속성 및 처리 클래스의 설정 방법에 대해서도 알아보았다.
다음 3회 글에서는 OR 매핑의 한 부분인 Object, 즉, Hibernate가 데이터를 메모리 상에서 표현할 자바 퍼시스턴트 클래스의 작성 방법에 대해서 살펴볼 것이다.
관련링크:
Hibernate의 세션 설정 방법 및 프로퍼티 설정 방법
Hibernate API를 사용하는 기본 코드는 아래와 같은 형태를 띄고 있다.
// 1. 초기화 메소드에서 SessionFactory를 초기화한다.
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
// 2. 실제 메소드에서는 sessionFactory에서 Session을 생성해서 사용한다.
Session s = sessionFactory.openSession();
... // Session을 사용해서 CRUD 실행
s.close();
Configuration cfg = new Configuration();
cfg.configure();
SessionFactory sessionFactory = cfg.buildSessionFactory();
// 2. 실제 메소드에서는 sessionFactory에서 Session을 생성해서 사용한다.
Session s = sessionFactory.openSession();
... // Session을 사용해서 CRUD 실행
s.close();
코드는 크게
- OR 매핑 정보 및 커넥션 프로퍼티 정보를 담고 있는 Configuration을 생성하고, Configuration으로부터 SessionFactory를 생성하는 부분과
- SessionFactory로부터 Session을 구해 CRUD 작업을 처리하는 부분
Hibernate Session 생성 방법
Session은 데이터베이스 세션을 의미하는 것으로서, Session이 사용할 데이터베이스 커넥션을 구하는 방법은 다음과 같이 3가지가 존재한다.
- JNDI로부터 커넥션 DataSource를 받아서 Session에 전달하기
- Hibernate가 제공하는 커넥션 풀을 사용하기
- 직접 생성한 커넥션을 Session에 전달하기
프로퍼티 정보 명시하기
커넥션 정보는 프로퍼티를 통해서 명시할 수 있는데, 프로퍼티는 4가지 방법으로 지정할 수 있다. Hibernate는 다음의 순서대로 프로퍼티 정보를 읽어온다.
- Configuration.setProperties() 메소드에 전달된 java.util.Properties에 저장된 프로퍼티 정보
- 클래스패스 루트에 위치한 hibernate.properties 파일에 저장된 프로퍼티 정보
- java -Dproperty=value를 사용해서 전달된 시스템 프로퍼티
- hibernate.cfg.xml 파일에 <property> 태그로 명시한 프로퍼티 정보
위의 네 가지 방법 중에서 두번째와 네번째는 파일을 클래스패스 루트에 위치시키면 다음의 코드를 통해서 Hibernate가 설정 파일로부터 프로퍼티를 읽어온다.
Configuration cfg = new Configuration().configure();
// 또는 아래와 같이 두줄로 실행
// Configuration cfg = new Configuration();
// cfg.configure();
// 또는 아래와 같이 두줄로 실행
// Configuration cfg = new Configuration();
// cfg.configure();
하지만, 첫번째 방법을 사용하고 싶다면 아래와 같이 직접 코드에서 Properties 객체를 생성한 뒤 Configuration 객체에 전달해주어야 한다.
Properties prop = new Properties();
prop.setProperty(...);
...
Configuration cfg = new Configuration();
cfg.setProperties(prop);
prop.setProperty(...);
...
Configuration cfg = new Configuration();
cfg.setProperties(prop);
네 가지 방법 중 어떤 방법으로 사용하더라도 Hibernate가 사용하는 프로퍼티의 이름과 값의 의미는 동일하므로, 본 글에서는 XML 파일 포맷인 hibernate.cfg.xml 파일에 프로퍼티 정보를 명시하는 방법을 사용해서 커넥션 정보를 명시하는 형태로 예제를 보여줄 것이다.
Sessin 설정 방법: JNDI 설정/커넥션 풀/직접 커넥션 제공
앞서 말했듯이 Hibernate Session이 사용할 데이터베이스 커넥션을 JNDI나 Hibernate의 커넥션 풀로부터 얻어오거나 또는 사용자가 직접 제공한 커넥션을 사용할 수도 있다.
JNDI 설정
Hibernate가 JNDI에 바인딩된 DataSource로부터 데이터베이스 커네션을 구하도록 설정하려면 다음과 같은 프로퍼티를 사용하면 된다.
프로퍼티 이름 | 값 |
hibernate.connection.datasource | DataSource의 JNDI 이름 |
hibernate.jndi.url | JNDI 제공자의 URL (옵션) |
hibernate.jndi.class | JNDI의 InitialContextFactory의 클래스 (옵션) |
hibernate.connection.username | 데이터베이스 사용자 (옵션) |
hibernate.connection.password | 데이터베이스 사용자 암호 (옵션) |
예를 들어, JNDI에 등록된 DataSource의 이름이 "hibernate" 라면 다음과 같이 connection.datasource 프로퍼티 값을 설정해주면 된다. (위 표에 있는 나머지 프로퍼티들은 대부분의 WAS에서 설정하지 않아도 문제가 되지 않는다.)
<?xml version="1.0" encoding="euc-kr" ?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">hibernate</property>
<property name="hibernate.transaction.factory_class">
net.sf.hibernate.transaction.JTATransactionFactory
</property>
<property name="hibernate.trasaction.manager_lookup_class">
net.sf.hibernate.transaction.WeblogicTransactionManagerLookup
</property>
<property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property>
<mapping resource="Cat.hbm.xml" />
</session-factory>
</hibernate-configuration>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">hibernate</property>
<property name="hibernate.transaction.factory_class">
net.sf.hibernate.transaction.JTATransactionFactory
</property>
<property name="hibernate.trasaction.manager_lookup_class">
net.sf.hibernate.transaction.WeblogicTransactionManagerLookup
</property>
<property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property>
<mapping resource="Cat.hbm.xml" />
</session-factory>
</hibernate-configuration>
위 프로퍼티에서 DataSource외에 나머지 프로퍼티에 대해서 'SQL Dialect와 트랜잭션 전략 설정' 부분에서 설명할 것이므로 아직까진 신경쓰지 말기 바란다.
간단하게 톰캣의 예를 들어, 데이터 소스 설정 예제를 살펴보도록 하겠다. 참고로, 여기서 보여주는 예제는 지난 1회 글 'Hibernate를 이용한 ORM 1 - 퀵 스타트'에서 사용한 예제에서 설정 파일부분만 변경한 것이다.
먼저 톰캣에 웹 어플리케이션에서 사용할 DataSource에 대한 JNDI 설정을 추가해야 한다. 이 설정은 [톰캣]/conf/server.xml 파일에 추가하면 되며, 아래와 같은 형태의 코드를 사용하면 된다. (톰캣에서 DataSource를 추가하는 방법에 대한 자세한 내용은 톰캣 사이트인 http://jakarta.apache.org/tomcat/을 참고하기 바란다.)
파일 [톰캣]/config/server.xml에 추가할 내용
<Host ...>
...
<Context path="/hibernate" docBase="hibernate">
<Resource name="jdbc/hibernate" auth="Container"
scope="Shareable" type="javax.sql.DataSource" />
<ResourceParams name="jdbc/hibernate">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@localhost:1521:ORA</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</parameter>
<parameter>
<name>username</name>
<value>scott</value>
</parameter>
<parameter>
<name>password</name>
<value>tiger</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>3000</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>100</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>10</value>
</parameter>
</ResourceParams>
</Context>
...
</Host>
<Host ...>
...
<Context path="/hibernate" docBase="hibernate">
<Resource name="jdbc/hibernate" auth="Container"
scope="Shareable" type="javax.sql.DataSource" />
<ResourceParams name="jdbc/hibernate">
<parameter>
<name>factory</name>
<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
</parameter>
<parameter>
<name>url</name>
<value>jdbc:oracle:thin:@localhost:1521:ORA</value>
</parameter>
<parameter>
<name>driverClassName</name>
<value>oracle.jdbc.driver.OracleDriver</value>
</parameter>
<parameter>
<name>username</name>
<value>scott</value>
</parameter>
<parameter>
<name>password</name>
<value>tiger</value>
</parameter>
<parameter>
<name>maxWait</name>
<value>3000</value>
</parameter>
<parameter>
<name>maxIdle</name>
<value>100</value>
</parameter>
<parameter>
<name>maxActive</name>
<value>10</value>
</parameter>
</ResourceParams>
</Context>
...
</Host>
위 코드에서는 JNDI에 등록될 DataSource의 이름을 "jdbc/hibernate"로 지정하였는데, 이는 실제로 "java:comp/env/" 콘텍스트에 추가되므로 설정한 DataSource의 완전한 JNDI 이름은 "java:comp/env/jdbc/hibernate"가 된다. 따라서, Hibernate의 설정 파일에 아래와 같이 hibernate.connection.datasource 프로퍼티의 값을 주면 된다.
파일경로: [톰캣]/webapps/hibernate/WEB-INF/classes/hibernate.cfg.xml
<?xml version="1.0" encoding="euc-kr" ?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/hibernate</property>
<property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property>
<mapping resource="Cat.hbm.xml" />
</session-factory>
</hibernate-configuration>
<?xml version="1.0" encoding="euc-kr" ?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.datasource">java:comp/env/jdbc/hibernate</property>
<property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property>
<mapping resource="Cat.hbm.xml" />
</session-factory>
</hibernate-configuration>
어플리케이션 서버(톰캣)에 DataSource를 JNDI에 등록하고, JNDI를 사용하도록 Hibernate의 프로퍼티를 설정하면 모든 게 완료된다. 소스 코드는 전혀 변경할 필요가 없이 이 두가지만 변경해주면 1회에 작성했던 예제를 실행할 수 있을 것이다.
커넥션 풀 설정
Hibernate는 자체적으로 커넥션 풀 기능을 제공하고 있는데, Hibernate Session이 커넥션 풀로부터 필요한 데이터베이스 커넥션을 구하도록 설정할 수 있다. 기본적인 설정 방법은 다음과 같다.
<?xml version="1.0" encoding="euc-kr" ?>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">JDBC 드라이버 클래스</property>
<property name="hibernate.connection.url">JDBC URL</property>
<property name="hibernate.connection.username">DB User</property>
<property name="hibernate.connection.password">DB User Password;/property>
<property name="hibernate.connection.pool_size">DB User Password;/property>
...
</session-factory>
</hibernate-configuration>
<!DOCTYPE hibernate-configuration
PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">JDBC 드라이버 클래스</property>
<property name="hibernate.connection.url">JDBC URL</property>
<property name="hibernate.connection.username">DB User</property>
<property name="hibernate.connection.password">DB User Password;/property>
<property name="hibernate.connection.pool_size">DB User Password;/property>
...
</session-factory>
</hibernate-configuration>
위의 설정 내용을 보면 알겠지만, Hibernate Session이 Hibernate가 제공하는 커넥션 풀을 사용하도록 설정하려면 다음의 네 가지 기본 프로퍼티를 요구한다.
- hibernate.connection.driver_class - DB 연결시 사용할 JDBC 드라이버 클래스
- hibernate.connection.url - JDBC URL
- hibernate.connection.username - DB 사용자 이름
- hibernate.connection.password - DB 사용자 암호
- hibernate.connection.pool_size - 커넥션 풀의 최대 크기 명시. (선택)
DBCP 관련 프로퍼티
- DBCP를 실행하는 데 필요한 jar 파일을 복사한다. 이 파일들은 hibernate 배포판의 lib/ 폴더에 포함되어 있다. 웹 어플리케이션이라면 DBCP 관련 jar 파일들을 WEB-INF/lib 폴더에 복사해주면된다.
commons-dbcp-1.2.1.jar, commons-collections-2.1.1.jar, commons-pool-1.2.jar
- DBCP 관련 프로퍼티를 설정한다.
프로퍼티 이름 | 값 |
hibernate.dbcp.maxActive | 한번에 풀에서 갖다 쓸 수 있는 최대 커넥션 개수 |
hibernate.dbcp.whenExhaustedAction | 풀에서 더이상 가져올 수 있는 커넥션이 없을 때 어떻게 처리할지를 명시한다. 값이 1이면, 풀에서 가져올 커넥션이 생길 때 까지 블럭킹된다. 값이 2이면, 풀은 새로운 커넥션을 생성해서 리턴한다. 값이 0이면, 에러를 발생시킨다. 기본값은 1이다. |
hibernate.dbcp.maxWait | hibernate.dbcp.whenExhaustedAction 프로퍼티의 값이 1인 경우, 블럭킹될 시간을 1/1000초 단위로 지정한다. 0보다 작으면 무한히 대기한다. |
hibernate.dbcp.maxIdle | 사용되지 않고 풀에 저장될 수 있는 최대 커넥션 개수 |
hibernate.dbcp.validationQuery | 커넥션을 가져올 때 커넥션의 유효성 여부를 검사할 쿼리를 입력한다. 예를 들어, 오라클인 경우 select count(*) from dual과 같은 쿼리를 사용할 수 있다. |
hibernate.dbcp.testOnBorrow | true이면 풀에서 커넥션을 가져올 때 커넥션이 유효한지 검사한다. |
hibernate.dbcp.testOnReturn | true이면 커넥션을 풀에 반환할 때 커넥션이 유효한지 검사한다. |
위의 모든 프로퍼티를 지정할 필요는 없으며, hibernate.dbcp. 로 시작하는 프로퍼티가 존재하면 Hibernate는 DBCP를 커넥션 풀 모듈로 사용하게 된다.
커넥션 Session에 직접 전달
앞서 두 가지 방법, 즉 JNDI를 사용하는 방법과 커넥션 풀을 사용하는 방법은 Hibernate의 프로퍼티로 설정할 수 있었다. 그런데 부득이한 이유로 JNDI나 커넥션 풀을 사용할 수 없는 경우도 있을 것이다. 예를 들어, 기존 커넥션 관련 모듈이 있어서 Hibernate도 이 모듈에서 제공하는 커넥션을 사용해야 하는 경우가 발생할 수 있다.
이런 경우에는 커넥션 관련된 Hibernate 프로퍼티에서 설정할 값이 없으며, 다음과 같이 SessionFactory.openSession(Connection conn) 메소드를 호출해서 Session 객체를 생성하면 된다.
SessionFactory sessionFactory = ....;
Connectoin conn = ...;
Session session = sessionFactory.openSession(conn);
...
session.close();
conn.close();
Connectoin conn = ...;
Session session = sessionFactory.openSession(conn);
...
session.close();
conn.close();
직접 커넥션을 Session에 전달할 때 주의할 점은, 하나의 JDBC 커넥션에 대해서 동시에 두 개의 열린 Session을 생성해서는 안 된다는 점이다. 즉, 다음과 같은 코드를 작성하지 않도록 주의해야 한다.
Connectoin conn = ...;
Session session1 = sessionFactory.openSession(conn);
Session session2 = sessionFactory.openSession(conn); // 같은 커넥션으로 Session 생성
...
session1.close();
session2.close();
...
conn.close();
Session session1 = sessionFactory.openSession(conn);
Session session2 = sessionFactory.openSession(conn); // 같은 커넥션으로 Session 생성
...
session1.close();
session2.close();
...
conn.close();
SQL Dialect와 트랜잭션 속성/처리 클래스 설정
Hibernate는 DBMS에 따라서 최적화된 기능을 제공할 수 있으며, 또한 사용할 어플리케이션 서버에 알맞은 트랜잭션 기능을 제공할 수 있다. DBMS에 최적화된 기능을 제공하기 위해 사용되는 것이 SQL Dialect이며, hibernate.trasaction.manager_lookup_class 프로퍼티를 통해서 트랜잭션 처리 클래스를 설정할 수 있다.
SQL Dialect
Hibernate는 특정 DBMS가 제공하는 기능을 사용할 수 있는 기능을 제공하며, Dialect 프로퍼티를 사용해서 이 기능을 사용할 수 있다. 예를 들어, Hibernate는 오라클를 사용할 때는 오라클에 최적화되도록 기능을 수행하며 MySQL을 사용하는 경우에는 MySQL에 최적화되도록 기능을 수행할 수 있다. 예를 들어, 오라클에 알맞은 Dialect를 설정하면, Hibernate는 시퀀스와 같이 DBMS에 특징적인 기능을 개발자가 직접 코딩하지 않고도 사용할 수 있게 된다.
hibernate.dialect 프로퍼티 값을 명시하면 SQL Dialect를 설정할 수 있는데, 각 DBMS에 따라 다음 표와 같이 프로퍼티값을 명시하면 된다.
DBMS | 프로퍼티값 |
DB2 | net.sf.hibernate.dialect.DB2Dialect |
DB2 AS/400 | net.sf.hibernate.dialect.DB2400Dialect |
DB2 OS390 | net.sf.hibernate.dialect.DB239Dialect |
PostgreSQL | net.sf.hibernate.dialect.PostgreSQLDialect |
MySQL | net.sf.hibernate.dialect.MySQLDialect |
Oracle (모든 버전) | net.sf.hibernate.dialect.OracleDialect |
Oracle 9/10g | net.sf.hibernate.dialect.Oracle9Dialect |
Sybase | net.sf.hibernate.dialect.SybaseDialect |
Sybase Anywhere | net.sf.hibernate.dialect.SybaseAnywhereDialect |
Microsoft SQL Server | net.sf.hibernate.dialect.SQLServerDialect |
SAP DB | net.sf.hibernate.dialect.SAPDBDialect |
Informix | net.sf.hibernate.dialect.InformixDialect |
HypersonicSQL | net.sf.hibernate.dialect.HSQLDialect |
Ingres | net.sf.hibernate.dialect.IngresDialect |
Progress | net.sf.hibernate.dialect.ProgressDialect |
Mckoi SQL | net.sf.hibernate.dialect.MckoiDialect |
Interbase | net.sf.hibernate.dialect.InterbaseDialect |
Pointbase | net.sf.hibernate.dialect.PointbaseDialect |
FrontBase | net.sf.hibernate.dialect.FrontbaseDialect |
Firebird | net.sf.hibernate.dialect.FirebirdDialect |
트랜잭션 속성 및 처리 클래스 설정
Hibernate의 Transaction 객체를 사용하기 위해서는 hibernate.transaction.factory_class 프로퍼티 속성을 설정해야 한다. 이 속성을 통해서 사용할 Transaction 구현체를 명시하게 된다. Hibernate는 기본적으로 두 가지 Transaction 구현체를 제공하고 있으며, 이 두 구현체는 다음과 같다.
- net.sf.hibernate.transaction.JDBCTransactionFactory
JDBC 트랜잭션에 트랜잭션 처리를 위임한다. - net.sf.hibernate.transaction.JTATransactionFactory
JTA에 처리를 위임한다. (기존의 트랜잭션이 존재하면 그 트랜잭션을 따르고, 존재하지 않을 경우 Session은 새로운 트랜잭션을 수행한다.
JTA 환경에서 변경가능한 데이터를 JVM 레벨에서 캐싱하기 위해서는, JTA TransactionManager를 구하기 위한 전력을 명시해야 한다. JTA TransactionManager를 구할 클래스를 명시할 때에는 hibernate.transaction.manager_lookup_class 프로퍼티의 값을 WAS에 따라 알맞게 명시하면 된다. 아래표는 WAS에 따라 사용할 프로퍼티 값 목록이다.
WAS | 프로퍼티값 |
JBoss | net.sf.hibernate.transaction.JBossTransactionManagerLookup |
Weblogic | net.sf.hibernate.transaction.WeblogicTransactionManagerLookup |
WebSphere | net.sf.hibernate.transaction.WebSphereTransactionManagerLookup |
Orion | net.sf.hibernate.transaction.OrionTransactionManagerLookup |
Resin | net.sf.hibernate.transaction.ResinTransactionManagerLookup |
JOTM | net.sf.hibernate.transaction.JOTMTransactionManagerLookup |
JOnAS | net.sf.hibernate.transaction.JOnASTransactionManagerLookup |
JRun4 | net.sf.hibernate.transaction.JRun4TransactionManagerLookup |
Borland ES | net.sf.hibernate.transaction.BESTransactionManagerLookup |
SessionFactory JNDI 등록
hibernate.session_factory_name 프로퍼티를 사용해서 JNDI 이름공간에 SessionFactory를 등록할 수 있다. hibernate.session_factory_name 프로퍼티의 값은 SessionFactory를 JNDI에 등록할 때 사용될 이름이 된다. 예를 들어, java:comp/env/hibernate/SessionFactory와 같은 이름을 사용하게 된다.
hibernate.session_factory_name 프로퍼티를 생략하면 SessionFactory를 JNDI에 등록하지 않는다. Tomcat과 같이 읽기전용 JNDI 구현체를 사용하는 서버에서는 hibernate.session_factory_name 프로퍼티 값을 설정하지 않는 것이 좋다.
hibernate.jndi.url 프로퍼티와 hibernate.jndi.class 프로터리를 사용해서 SessionFactory를 JNDI에 등록할 때 사용할 InitialContext를 명시할 수 있다. 이 속성값을 명시하지 않으면 기본 InitialContext가 사용된다.
다음 글에서는
이번 2회에서는 Hibernate가 사용할 데이터베이스 세션을 설정하는 세 가지 방법, 즉 JNDI를 이용하는 방법, 커넥션 풀을 사용하는 방법, 그리고 직접 코드에서 커넥션을 제공하는 방법에 대해서 살펴보았다. 그리고 DBMS의 기능을 활용할 수 있는 SQL Dialect 설정 방법과 WAS 서버에 따라 달라지는 JNDI 트랜잭션 속성 및 처리 클래스의 설정 방법에 대해서도 알아보았다.
다음 3회 글에서는 OR 매핑의 한 부분인 Object, 즉, Hibernate가 데이터를 메모리 상에서 표현할 자바 퍼시스턴트 클래스의 작성 방법에 대해서 살펴볼 것이다.
관련링크: