복붙노트

[SPRING] 주석 기반의 트랜잭션 관리와 객체 매핑을위한 Spring 3의 최소 Hibernate 4 XML 설정?

SPRING

주석 기반의 트랜잭션 관리와 객체 매핑을위한 Spring 3의 최소 Hibernate 4 XML 설정?

Spring 3 XML 설정으로 Hibernate 4를 추가하는 데 필요한 최소한의 설정은 무엇인지 이미 알고있는 Spring 프로젝트가 있다고 가정한다. 주석 기반 트랜잭션 관리를 사용하고 주석을 사용하여 매핑 된 객체를 원합니다.

참고 : 이것은 일반적인 문제에 대한 정식 답을 제공하기위한 자체 응답 Q & A 스타일 질문입니다. 나는이 질문을 Hibernate를 최신 상태로 유지하기 위해 시간이 지남에 따라 확장하고자한다.

해결법

  1. ==============================

    1.Spring의 XML 설정과 함께 Hibernate를 사용하는 것은 상당히 직관적이지만, 이전에 프로젝트에 추가 한 적이 없다면 올바르게 작동하는 것이 고통 스러울 수 있습니다. Spring의 XML 설정을 사용하는 것이 Hibernate 4에서 가장 선호되는 옵션이다.

    Spring의 XML 설정과 함께 Hibernate를 사용하는 것은 상당히 직관적이지만, 이전에 프로젝트에 추가 한 적이 없다면 올바르게 작동하는 것이 고통 스러울 수 있습니다. Spring의 XML 설정을 사용하는 것이 Hibernate 4에서 가장 선호되는 옵션이다.

    그래서 Spring 프로젝트를 설정하고 모든 것이 작동하도록했습니다. 이제 Hibernate를 추가하길 원한다.

    나는 WEB-INF 디렉토리 안에 database-servlet.xml과 같은 별도의 XML 파일로 Hibernate를 구성하는 것을 항상 좋아하지만 클래스 패스에서 이름만큼 중요하지는 않다.

    내 새 database-servlet.xml은 다음과 같습니다.

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
    
    </beans>
    

    tx 및 jdbc 스프링 네임 스페이스를 가져 왔음을 알 수 있습니다. 왜냐하면이 config 파일에서 꽤 많이 사용하기 때문입니다.

    가장 먼저 할 일은 주석 기반 트랜잭션 관리 (@Transactional)를 활성화하는 것입니다. 사람들이 Spring에서 Hibernate를 사용하는 주요 이유는 Spring이 당신을위한 모든 트랜잭션을 관리하기 때문입니다. 구성 파일에 다음 행을 추가하십시오.

    <tx:annotation-driven />
    

    데이터 소스를 만들어야합니다. 데이터 소스는 기본적으로 Hibernate가 객체를 지속시키기 위해 사용할 데이터베이스이다. 일반적으로 하나의 트랜잭션 관리자는 하나의 데이터 소스를 갖습니다. 당신이 Hibernate로 하여금 여러 데이터 소스들과 대화하기를 원한다면, 당신은 여러 트랜잭션 관리자들을 가진다.

    데이터 원본의 유형은 원하는 대상에 따라 달라집니다. 기존 데이터베이스를 지정하거나 Spring에 미리 패키징 된 새로운 메모리 내 HSQL / Derby / H2 데이터베이스를 생성 할 수 있습니다. 개인적으로 필자는 실제 테스트를 위해 프로젝트를 배포 할 때 Hibernate가 연결하는 기존 데이터베이스를 가지고 있지만 유닛 / 통합 테스트를 위해 메모리 내장 데이터베이스를 사용합니다.

    먼저 메모리 내 데이터베이스를 만드는 방법을 보여 드리겠습니다.

    <jdbc:embedded-database id="dataSource" type="HSQL">
        <jdbc:script location="classpath:/setup.sql" />
        .
        .
        .
        <!-- As many scripts can run as you like -->
    </jdbc:embedded-database>
    

    위의 설정은 bean으로 내장 (메모리 내장) HSQL 데이터베이스를 생성하고, setup.sql 스크립트를 실행 한 다음, dataSource 빈을 애플리케이션 컨텍스트에서 사용할 수 있도록합니다. HSQL이 기본값이기 때문에 데이터베이스 타입을 지정할 필요는 없지만, 나는 항상 명확하게하고 싶다. setup.sql은 클래스 경로 (일반적으로 WEB-INF 디렉토리) 내의 어느 위치 에나 위치 할 수 있습니다. 원하는만큼 SQL 스크립트를 지정할 수 있습니다. 또한 데이터베이스 작성 또는 제거시이를 실행해야하는지 설정할 수 있습니다.

    이 데이터베이스는 응용 프로그램과 함께 살고 죽을 것입니다. 프로덕션 프로젝트에 내장 데이터베이스를 사용하지 마십시오. 단 한 번의 정전만으로 모든 데이터가 사라집니다.

    데이터 원본을 기존 데이터베이스에 연결하려면 구성이 약간 다릅니다.

    <bean id="dataSource" 
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="" />
        <property name="url" value="" />
        <property name="username" value="" />
        <property name="password" value="" />
    </bean>
    

    이 bean의 클래스는 javax.sql.DataSource를 구현하는 모든 것이 될 수 있으므로 직접 작성할 수 있습니다. 이 예제 클래스는 Spring에 의해 제공되지만 자체 스레드 풀을 가지고 있지 않습니다. 보편적 인 대안은 Apache Commons org.apache.commons.dbcp.BasicDataSource이지만 다른 많은 것들이 있습니다. 아래의 각 속성에 대해 설명하겠습니다.

    다음은 SessionFactory를 설정하는 것입니다. 이것은 Hibernate가 당신의 트랜잭션을 생성하고 관리하는데 사용하는 것이며, 실제로 데이터베이스와 대화한다. 아래에 설명하려고하는 몇 가지 구성 옵션이 있습니다.

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="au.com.project />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.use_sql_comments">true</prop>
                <prop key="hibernate.hbm2ddl.auto">validate</prop>
            </props>
        </property>
    </bean>
    
    <property name="annotatedClasses">
        <list>
            <value>foo.bar.package.model.Person</value>
            <value>foo.bar.package.model.Thing</value>
        </list>
    </property>
    

    선언해야 할 마지막 두 가지 bean은 다음과 같습니다.

    <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
        id="PersistenceExceptionTranslator" />
    
    <bean id="transactionManager" 
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    

    PersistenceExceptionTranslator는 데이터베이스 특정 HibernateException 또는 SQLExceptions를 응용 프로그램 컨텍스트가 이해할 수있는 Spring 예외로 변환합니다.

    TransactionManager 빈은 롤백뿐만 아니라 트랜잭션을 제어합니다.

    참고 : DAO에 SessionFactory bean을 autowiring해야합니다.

    일단 당신이 이것을했다. web.xml 파일에 새 database-servlet.xml을 추가하기 만하면됩니다.

    <context-param>
    <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/database-servlet.xml
            .
            .
            .
        </param-value>
    </context-param>
    

    이것은 실제로 당신이 Hibernate 작업을하기 위해 필요한 모든 것이어야한다. 개체에 주석을 추가하고 DAO와 상호 작용하는 서비스 계층 메서드에 @Transactional을 추가해야합니다.

    편리한 힌트 : Ivy 나 maven과 같은 의존성 관리자를 사용하고 있고 모든 Spring & Hibernate javadocs를 가져온다면 STS XML 편집기에서 속성 위로 마우스를 가져 가면 실제로 볼 수 있습니다.

    이 모든 것이 실제로 어떻게 작용하는지

    서비스 클래스에서 @Transactional을 사용하여 메소드에 주석을 달고 그 메소드를 다른 곳에서 호출하면 몇 가지 일이 발생합니다. Hibernate TransactionManager는 메소드가 호출되기 전에 AOP pointcut을 사용하여 코드를 주입한다. 이것은 TransactionManager가 (특별한 순서없이) 다음을 수행 할 곳입니다.

    이 시점부터 트랜잭션 관리자는 발견 한 영구 객체뿐만 아니라 현재 세션을 통해 실행되는 모든 변경 사항을 기록합니다. 예외를 throw 할 경우 메소드가 호출 된 이후에 발생한 모든 것을 롤백하는 것이 중요합니다.

    SessionFactory 빈은 TransactionManager가 생성을 요구하는 모든 데이터베이스 세션을 생성, 유지, 닫기 및 플러시하는 역할을 담당한다. 이것이 우리가 DAO에 SessionFactory를 autowire하고 그것을 통해 모든 쿼리를 실행하는 이유입니다.

    새로운 Hibernate 사용자가 묻는 가장 큰 질문 중 하나는 "언제 내 변경 사항이 커밋 되나요?"입니다. 트랜잭션 관리자가 SesisonFactory와 함께 작동하는 방식을 생각할 때 답이 맞습니다. @Transactional로 주석 처리 된 서비스 메소드를 종료하면 데이터베이스 변경 사항이 플러시되고 커밋됩니다. 그 이유는 트랜잭션이 끊어짐없는 작업의 단일 단위를 나타 내기 때문입니다. 유닛에 문제가 발생하면 유닛이 실패하고 모든 변경 사항을 롤백해야한다고 가정합니다. 따라서 SessionFactory는 원래 호출 한 서비스 메소드를 종료 할 때 세션을 비우고 지 웁니다.

    그것은 트랜잭션이 진행되는 동안 세션을 비우고 지우지 않는다는 것을 의미하지는 않습니다. 예를 들어 서비스 메소드를 호출하여 5 개의 객체 컬렉션을 추가하고 데이터베이스에있는 객체의 총 개수를 반환하면 SessionFactory는 쿼리 (SELECT COUNT (*))가 업데이트 된 상태가 정확해야 함을 인식하고 카운트 쿼리를 실행하기 전에 5 개의 개체를 추가하여 플러시합니다. 실행은 다음과 같이 보일 수 있습니다.

    //Service
    @Override
    @Transactional
    public long saveAndCount(List<Foo> listOfFoo){
        for(Foo foo : listOfFoo){
            //Doesn't get instantly saved to the database.
            fooDAO.saveOrUpdate(foo);
        }
        /*
         * Before the actual SELECT COUNT(*) query was run, the SessionFactory would
         * flush the save operation of the 5 Foo objects.
         */
        return fooDAO.count();
    }
    

    분명한 것은, DAO는 세션 관리 코드가 전혀 없다는 것이다. 그것은 sessionFactory.getCurrentSession ()의 라인을 따라 뭔가있을 것에서는 BuildCriteria (foo.class 위를).; 그리고 그게 다야. Session 객체의 조작 인스턴스가 없으며 flush () 또는 clear ()를 호출하지 않습니다. Spring과 함께 Hibernate를 사용하는 것의 아름다움입니다.

    기권: 이 예제가 스텐다드 안정제로 작동하는 경우에는 알지 못합니다.

    나는 어떤 식 으로든 Hibernate 나 Hibernate 개발팀과 관련이 없다. 이 예제들을 제공하고 있으므로 Hibernate 태그에 질문에 대답 할 때를 가리키는 참조가 있습니다. 이 예제와 토론은 내 자신의 견해와 Hibernate를 사용하여 내 어플리케이션을 어떻게 개발하는지에 근거한다. 이 예제는 포괄적 인 것은 아닙니다. 나는 Hibernate를 과거에 사용했던 일반적인 상황에 기초하고있다.

    이 예제를 구현하는 데 문제가 발생하는 경우 코멘트하지 말고 문제를 해결하길 기대하십시오. 최대 절전 모드를 배우는 부분은 in 및 out을 배우고 있습니다. 그것의 API의. 예제와 함께 실수가 있으면 자유롭게 편집하십시오.

  2. from https://stackoverflow.com/questions/24422678/minimal-hibernate-4-xml-configuration-with-spring-3-for-annotation-based-transac by cc-by-sa and MIT license