Spring에서 Hibernate4로 MySQL 연동하는 예제

pom.xml에 하이버네이트 추가

1
2
3
4
5
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>4.3.1.Final</version>
</dependency>


이클립스에 하이버네이트 플러그인 설치

이클립스->Help->Install New Software->Work with : http://download.jboss.org/jbosstools/updates/stable 주소 입력

Hibernate tool를 검색해 설치

참고할 사이트


pom.xml에 mysql 연결 라이브러리 추가

1
2
3
4
5
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.28</version>
</dependency>           


디비 커넥션 풀 관리자 소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
 
public class HibernateUtil {
   private static final SessionFactory sessionFactory;
   private static final ServiceRegistry serviceRegistry;
   static {
      try {
            // Create the SessionFactory from hibernate.cfg.xml
            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();       
            sessionFactory = configuration.buildSessionFactory(serviceRegistry);
             
      } catch (Throwable ex) {
         // Make sure you log the exception, as it might be swallowed
         System.err.println("Initial SessionFactory creation failed." + ex);
         throw new ExceptionInInitializerError(ex);
      }
   }
 
   private static final ThreadLocal<Session> session = new ThreadLocal<Session>();
 
   public static Session getCurrentSession() throws HibernateException {
      Session s = session.get();
      // Open a new Session, if this thread has none yet
      if (s == null) {
         s = sessionFactory.openSession();
         // Store it in the ThreadLocal variable
         session.set(s);
      }
      return s;
   }
 
   public static void closeSession() throws HibernateException {
      Session s = (Session) session.get();
      if (s != null)
         s.close();
      session.set(null);
   }
}

애노테이션을 사용해 디비테이블과 연동될 클래스 정의

JPA 애노테이션을 사용하므로, javax.persistence.* package를 사용해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
 
 
 
@Entity
@Table(name = "mytable")
public class MyTestTable {
 
    @Id @GeneratedValue
    private Integer id;
     
    @NotNull @Column(updatable=false)
    private String name;
     
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
     
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
     
     
}

MVC 컨틀롤러에 테스트 코드 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RequestMapping(value="/dbtest1")
public String dbtest1(){
  
    Session session = null;
     
   
    try {
        // 세션 열기
        session = HibernateUtil.getCurrentSession();
        MyTestTable entity = (MyTestTable)session.get(MyTestTable.class, 1);
        logger.info("Welcome dbtest user {}.",entity.getName());   
    }
    catch (HibernateException e) {
        e.printStackTrace();
    }
    finally {
        // 세션 닫기
        HibernateUtil.closeSession();
    }
     
    return "home";
     
}

테스트 코드를 실행하면, 다음과 같은 메시지가 콘솔에 찍혀 있다.

최신버전에서는 dtd의 위치가 변경되었기 때문에 

제시된 위치로 hibernate.cfg.xml에 .dtd 위치를 변경

1
2
3
4
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"


  • Using Hibernate built-in connection pool (not for production use!)

내장된 커넥션 풀을 사용했다는 메시지이고, 개선된 커넥션 풀을 사용하면 해결된다.

하이버네이트용 커넥션 풀


 c3p0

 http://sourceforge.net/projects/c3p0

 Apache DBCP

 http://jakarta.apache.org/commons/dbcp/

 Proxool

 http://proxool.sourceforge.net/


여기서는 c3p0를 사용하여 connection pool설정한다.

hibernate.cfg.xml에 추가

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<session-factory>
        ...
        <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>       
        <property name="hibernate.c3p0.acquire_increment">1</property>
        <property name="hibernate.c3p0.idle_test_period">60</property>
        <property name="hibernate.c3p0.min_size">1</property>
        <property name="hibernate.c3p0.max_size">2</property>
        <property name="hibernate.c3p0.max_statements">50</property>
        <property name="hibernate.c3p0.timeout">0</property>
        <property name="hibernate.c3p0.acquireRetryAttempts">1</property>
        <property name="hibernate.c3p0.acquireRetryDelay">250</property>
 
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.use_sql_comments">true</property>
 
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
        <property name="hibernate.current_session_context_class">thread</property>
</session-factory>

pom.xml에 추가

위에서 설치한 Hibernate-core버전과 일치해야 한다.

1
2
3
4
5
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-c3p0</artifactId>
    <version>4.3.1.Final</version>
</dependency>


c3p0속성 설명


 acquire_increment

 풀이 고갈되었을 때, 신규로 생성할 커넥션 수

 idle_test_period

 풀에 있는 세션들이 살아있는지 체크하는 주기(초)

 디비서버가 재부팅되면, 풀에 등록된 세션들은 끊어진 세션이다.

 min_size

 풀의 최소 사이즈  

 max_size

 풀의 최대 사이즈 

 max_statements

 PreparedStatement 캐쉬의 사이즈

 모든 커넥션에서 사용가능한 사이즈

 커넥션 하나에서 사용하는 캐쉬 사이즈 * 커넥션 수(max_size)

 timeout

 풀에서 커넥션이 제거되는 시간(초)

 풀에서 사용되기를 기다리는 커넥션이 timeout 시간보다 오랫동안 사용되지 않았을 때 제거된다.

 0이면 제거되지 않는다.

 acquireRetryAttempts

 커넥션 생성 시도 수

 디비서버가 죽은 상태라면, 커넥션 생성이 실패될 것이고, 지정한 수만큼 시도하다가 그래도 실패한다면, 예외를 준다.

 acquireRetryDelay

 커넥션 생성 시도 쿨타임(밀리초)  



  • org.hibernate.MappingException: Unknown entity: com.yakolla.mvctest.MyTestTable

MyTestTable class가 디비테이블과 연동됨을 알리는 작업이 필요하다.

애노테이션을 이미 정의했지만, hibernate.cfg.xml에 추가해야 한다.

언젠간 자동으로 되겠지~

추가할 때 주의점은 <session-factory>의 <property>태크 정의가 끝난 이후부터 선언할 수 있다.

1
2
3
4
5
6
7
8
9
10
<session-factory>
     
        ...
 
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
        <property name="hibernate.current_session_context_class">thread</property>
         
        <mapping class="com.yakolla.mvctest.MyTestTable" />
     
    </session-factory>