Spring은 가장 많이 사용되는 Java EE 프레임워크 중 하나이며, Hibernate은 가장 인기 있는 ORM 프레임워크입니다. 그래서 기업 응용 프로그램에서는 Spring Hibernate 조합이 많이 사용됩니다. 최근에는 Spring Tutorial과 Hibernate Tutorial에 대해 많이 작성했으므로, spring hibernate integration에 대한 포스트가 오랜 시간 동안 예정되어 있었습니다.
Spring Hibernate
오늘 이 자습서에서는 Spring 4를 사용하여 Hibernate 3과 통합한 다음 동일한 프로젝트를 Hibernate 4로 업데이트할 것입니다. Spring과 Hibernate에는 많은 버전이 있으며, Spring ORM 아티팩트는 Hibernate 3과 Hibernate 4를 모두 지원하기 때문에 프로젝트에서 사용한 모든 종속성을 나열하는 것이 좋습니다. 알림: 나는 모든 Spring과 Hibernate 버전이 호환되지 않는 것을 알았고, 아래 버전은 작동했으므로 호환되는 것으로 생각합니다. 다른 버전을 사용하고 java.lang.NoClassDefFoundError
를 받으면 호환되지 않는 것입니다. 대부분의 경우 Hibernate 클래스가 오류를 일으키는 원인으로 한 패키지에서 다른 패키지로 이동되기 때문입니다. 예를 들어 최신 Hibernate 버전에서 org.hibernate.engine.FilterDefinition
클래스가 org.hibernate.engine.spi.FilterDefinition
로 이동되었습니다.
- Spring 프레임워크 버전: 4.0.3.RELEASE
- Hibernate Core 및 Hibernate EntityManager 버전: 3.6.9.Final 및 4.3.5.Final
- Spring ORM 버전: 4.0.3.RELEASE
데이터베이스 설정
I am using MySQL database for my project, so below setup.sql script will create the necessary table for this example.
CREATE TABLE `Person` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`country` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
commit;
Spring Hibernate 통합 예제 프로젝트 구조
아래 이미지는 최종 프로젝트 구조를 보여줍니다. 우리는 각 구성 요소를 하나씩 살펴볼 것입니다.
Maven 종속성
먼저 pom.xml 파일에서 필요한 종속성과 그 버전을 살펴보겠습니다.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringHibernateExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
<!-- Hibernate / JPA -->
<!-- <hibernate.version>4.3.5.Final</hibernate.version> -->
<hibernate.version>3.6.9.Final</hibernate.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring ORM support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
Spring과 Hibernate 통합 프로젝트에 필요한 중요한 종속성은 다음과 같습니다:
- 핵심 Spring 기능을 위한 spring-context 및 spring-tx. 버전 4.0.3.RELEASE를 사용하고 있음을 주목하세요.
- Spring ORM 지원을 위한 spring-orm 종속성은 스프링 프로젝트에서 하이버네이트 통합에 필요합니다.
- 하이버네이트 프레임워크를 위한 hibernate-entitymanager 및 hibernate-core 종속성. 버전은 3.6.9.Final이며, 하이버네이트 4를 사용하려면 위의 pom.xml 파일에 주석으로 표시된 대로 4.3.5.Final로 변경하면 됩니다.
- 데이터베이스 연결을 위한 MySQL 드라이버인 mysql-connector-java.
모델 클래스 또는 엔티티 빈
우리는 하이버네이트의 XML 기반 매핑과 JPA 주석 기반 매핑을 사용할 수 있습니다. 여기에서는 매핑을 위해 JPA 주석을 사용하고 있습니다. 이는 하이버네이트가 JPA 구현을 제공하기 때문입니다.
package com.journaldev.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Entity bean with JPA annotations
* Hibernate provides JPA implementation
* @author pankaj
*
*/
@Entity
@Table(name="Person")
public class Person {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private String country;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
DAO 클래스
DAO 클래스에서는 두 가지 메서드를 구현할 것입니다. 첫 번째는 Person 객체를 테이블에 저장하는 메서드이고, 두 번째는 테이블에서 모든 레코드를 가져와 Person의 리스트를 반환하는 메서드입니다.
package com.journaldev.dao;
import java.util.List;
import com.journaldev.model.Person;
public interface PersonDAO {
public void save(Person p);
public List<Person> list();
}
위의 DAO 클래스 구현은 다음과 같습니다.
package com.journaldev.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.model.Person;
public class PersonDAOImpl implements PersonDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void save(Person p) {
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(p);
tx.commit();
session.close();
}
@SuppressWarnings("unchecked")
@Override
public List<Person> list() {
Session session = this.sessionFactory.openSession();
List<Person> personList = session.createQuery("from Person").list();
session.close();
return personList;
}
}
주목할 점은 여기서만 하이버네이트 관련 클래스를 사용한다는 것입니다. 이 패턴은 구현을 유연하게 만들고 다른 기술로의 마이그레이션을 쉽게 할 수 있게 합니다. 예를 들어, iBatis ORM 프레임워크를 사용하고 싶다면, iBatis의 DAO 구현을 제공하고 스프링 빈 구성 파일을 변경하면 됩니다. 위의 예시에서는 하이버네이트 세션 트랜잭션 관리를 사용하고 있지만, @Transactional
주석을 사용하여 스프링의 선언적 트랜잭션 관리를 사용할 수도 있습니다. 자세한 내용은 Spring Transaction Management을 참조하세요.
Hibernate 3 통합을 위한 스프링 빈 구성 파일
우선 Hibernate 3 통합을 위해 필요한 스프링 빈 구성을 살펴보겠습니다. 나중에 자세히 살펴보겠습니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
xmlns:tx="https://www.springframework.org/schema/tx"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
<property name="username" value="pankaj" />
<property name="password" value="pankaj123" />
</bean>
<!-- Hibernate 3 XML SessionFactory Bean definition-->
<!-- <bean id="hibernate3SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean> -->
<!-- Hibernate 3 Annotation SessionFactory Bean definition-->
<bean id="hibernate3AnnotatedSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.journaldev.model.Person</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
<property name="sessionFactory" ref="hibernate3AnnotatedSessionFactory" />
</bean>
</beans>
데이터베이스 연결 세부 정보를 Hibernate에 제공하는 두 가지 방법이 있습니다. 첫째는 모든 것을 hibernateProperties
에 전달하는 것이고, 둘째는 DataSource를 생성한 다음 hibernate에 전달하는 것입니다. 저는 두 번째 접근 방식을 선호하기 때문에 Apache Commons DBCP 종속성을 사용하여 데이터베이스 연결 속성을 설정하여 BasicDataSource
를 생성합니다. 스프링과 Hibernate 3 통합을 위해, Spring ORM은 두 가지 클래스를 제공합니다. – hibernate 매핑이 XML 기반인 경우 org.springframework.orm.hibernate3.LocalSessionFactoryBean
및 주석 기반 매핑인 경우 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
입니다. XML 기반 매핑을 사용하는 경우 LocalSessionFactoryBean
의 간단한 빈 구성을 주석으로 제공했습니다. AnnotationSessionFactoryBean
은 LocalSessionFactoryBean
클래스를 확장하므로 hibernate 통합에 필요한 기본 속성을 모두 갖고 있습니다. 속성은 자체적으로 이해하기 쉽고 대부분 hibernate 관련이므로 자세히 설명하지 않겠습니다. 그러나 hibernateProperties, annotatedClasses가 어디에서 온 것인지 궁금하다면 빈 클래스의 소스 코드를 확인해야 합니다. personDAO의 빈 정의에 유의하세요. 앞서 말한대로 다른 ORM 프레임워크로 전환해야 하는 경우 여기서 구현 클래스를 변경하고 필요한 다른 속성을 설정해야 합니다.
Spring 4 Hibernate 3 테스트 프로그램
이제 설정이 준비되었으므로 애플리케이션을 테스트하는 간단한 프로그램을 작성해보겠습니다.
package com.journaldev.main;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.dao.PersonDAO;
import com.journaldev.model.Person;
public class SpringHibernateMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
Person person = new Person();
person.setName("Pankaj"); person.setCountry("India");
personDAO.save(person);
System.out.println("Person::"+person);
List list = personDAO.list();
for(Person p : list){
System.out.println("Person List::"+p);
}
// 리소스 닫기
context.close();
}
}
위의 프로그램을 실행하면 Hibernate와 관련된 많은 출력이 생성됩니다. 이는 로깅을 제대로 설정하지 않았기 때문입니다. 하지만 이 튜토리얼의 범위를 벗어나는 내용입니다. 그러나 우리의 프로그램이 생성한 다음 출력을 얻을 수 있습니다.
Person::id=3, name=Pankaj, country=India
Person List::id=1, name=Pankaj, country=India
Person List::id=2, name=Pankaj, country=India
Person List::id=3, name=Pankaj, country=India
Spring 4 Hibernate 4 통합 변경 사항
이제 Hibernate 3 대신 Hibernate 4를 사용하도록 애플리케이션을 변경해보겠습니다. 이 마이그레이션을 위해 다음과 같은 설정 변경만 필요합니다.
-
pom.xml 파일에서 Hibernate 버전을 4.3.5.Final로 변경하십시오. 위의 주석에 표시된 대로입니다.
-
스프링 빈 구성 파일을 변경하십시오. 지금까지 스프링 빈 구성 파일이 스프링과 하이버네이트 프레임워크의 통합의 핵심임을 알게 되었을 것입니다. 아래의 스프링 빈 구성 파일은 스프링 4와 하이버네이트 4 버전에 작동합니다.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop" xmlns:tx="https://www.springframework.org/schema/tx" xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/TestDB" /> <property name="username" value="pankaj" /> <property name="password" value="pankaj123" /> </bean> <!-- Hibernate 4 SessionFactory Bean definition --> <bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.journaldev.model.Person</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.current_session_context_class">thread</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> </bean> <bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl"> <property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" /> </bean> </beans>
하이버네이트 4의 경우, 세션 팩토리 빈에는
org.springframework.orm.hibernate4.LocalSessionFactoryBean
을 사용해야합니다. 스프링 ORM은 하이버네이트 3의 두 클래스를 병합했으며 이제는 하나의 클래스가 있습니다. 이렇게 함으로써 혼란을 피하는 데 도움이됩니다. 다른 모든 구성은 이전과 동일합니다.
그게 다입니다. 프로젝트가 성공적으로 하이버네이트 4로 이전되었습니다. 깔끔하죠? SpringHibernateMain
클래스를 변경하여 빈 구성에 spring4.xml
을 사용하면 잘 작동하며 이전과 동일한 결과를 얻을 수 있습니다. 아래 링크에서 최종 프로젝트를 다운로드하여 추가 구성을 통해 더 많이 배울 수 있습니다.
Source:
https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial