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

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

<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 연결 라이브러리 추가

<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.28</version> </dependency>


디비 커넥션 풀 관리자 소스

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를 사용해야 한다.

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 컨틀롤러에 테스트 코드 추가

@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 위치를 변경

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd>">


  • 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에 추가

<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버전과 일치해야 한다.

&lt;dependency&gt; &lt;groupId&gt;org.hibernate&lt;/groupId&gt; &lt;artifactId&gt;hibernate-c3p0&lt;/artifactId&gt; &lt;version&gt;4.3.1.Final&lt;/version&gt; &lt;/dependency&gt;


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>태크 정의가 끝난 이후부터 선언할 수 있다.

<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>