복붙노트

[SPRING] @Transactional 주석이있는 Spring OpenSessionInViewFilter

SPRING

@Transactional 주석이있는 Spring OpenSessionInViewFilter

이것은 서비스 레이어에서 @Transactional 주석을 사용하여 Spring OpenSessionInViewFilter에 관한 것입니다.

이 너무 많은 스택 오버플로 게시물을 통해 갔다하지만 여전히 OpenSessionInViewFilter 또는 LazyInitializationException 않도록하려면 사용해야하는지 혼란에 대해 혼란 스러워요. 누군가 아래의 질문에 대한 답변을 찾도록 도와 주면 큰 도움이 될 것입니다.

아래는 나의 Spring 설정 파일이다.

<context:component-scan base-package="com.test"/>
<context:annotation-config/>
 <bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="resources/messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
 <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
        p:location="/WEB-INF/jdbc.properties" />
 <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
        p:driverClassName="${jdbc.driverClassName}"
        p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
        p:password="${jdbc.password}" />
       <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />     
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${jdbc.dialect}</prop>
                <prop key="hibernate.show_sql">true</prop>
                <!--
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                 -->
            </props>
        </property>
    </bean>
 <tx:annotation-driven /> 
 <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />

  </bean>

해결법

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

    1.OpenSessionInView는 최대 절전 모드 세션을 열고 요청을 처리하는 스레드의 SessionHolder에 저장하는 것보다 서블릿 필터입니다. 이 세션이 열리면, hibernate는 요청의 렌더링 단계에서 이것을 사용할 때 Lazy 초기화 된 콜렉션과 객체를 읽을 수있다. 이 세션은 SessionFactory.getCurrentSession ()을 호출 할 때 액세스 할 수 있습니다.

    OpenSessionInView는 최대 절전 모드 세션을 열고 요청을 처리하는 스레드의 SessionHolder에 저장하는 것보다 서블릿 필터입니다. 이 세션이 열리면, hibernate는 요청의 렌더링 단계에서 이것을 사용할 때 Lazy 초기화 된 콜렉션과 객체를 읽을 수있다. 이 세션은 SessionFactory.getCurrentSession ()을 호출 할 때 액세스 할 수 있습니다.

    그러나 OpenSessionInView는 세션을 열뿐 트랜잭션을 시작하지 않습니다. 세션이 열리면 데이터베이스에서 객체를 읽을 수 있지만, 트랜잭션에서 무언가를하고 싶다면 @Transactional 어노테이션이나 원할 때 트랜잭션의 시작과 끝을 구별하는 다른 메커니즘이 필요합니다.

    그런 다음 질문의 대답 :

    이것은 LazyInitializationException을 피할 필요가 있고 과부하가 단지 새로운 Hibernate Session을 열고 각 요청에 대한 요청의 끝에서 그것을 닫을 때 좋은 연습이다.

    나는 많은 프로젝트에서이 필터를 사용하고 어떤 문제도 일으키지 않습니다.

    아닙니다. SessionHolder에서 열어 놓은 Hibernate Session 만 있습니다. 그러나 Transaction이 필요하다면 @Transactional을 넣어야합니다.

  2. ==============================

    2.내 0.02c 여기에 던져 (그리고 페르난도 Rincon의 훌륭한 답변 확대) :

    내 0.02c 여기에 던져 (그리고 페르난도 Rincon의 훌륭한 답변 확대) :

    LazyInitializationException을 피해야하기 때문에 OpenSessionInView 필터를 사용하면 안됩니다. 시스템에 혼란과 복잡성을 추가 할 것입니다. 프론트 엔드에서 콜렉션에 액세스해야하는 위치를 시스템 설계에서 정확히 알아야합니다. 거기에서, (내 경험상) 콜렉션을 검색하기 위해 서비스 메소드를 호출하는 컨트롤러 메소드를 만드는 것이 더 쉽다.

    그러나 OpenSessionInView 필터를 사용하여 해결할 수있는 또 다른 문제가 생기면 부작용으로 세션을 연다. 그런 다음 세션을 열어서 콜렉션에 액세스 할 때 해를 입지 않는다. 그러나 OpenSessionInView를 사용하여 한 위치에서 컬렉션 객체를 가져 오는 경우 다른 위치에서 코드를 리팩터링하여 컬렉션을 가져 오는 데 사용 된 전략이 응용 프로그램에서 표준화되도록해야합니다.

    OpenSessionInView 필터를 사용해야하는지 결정하기 위해 컨트롤러 및 서비스 메소드를 작성하는 비용과 비교하여이 리팩터의 비용을 비쌉니다.

  3. ==============================

    3.OpenSessionInViewFilter는 http 요청에 대한 최대 절전 모드 세션을 바인드하는 서블릿 필터이며 모든 HTTP 요청에 대해 트랜잭션 및 비 트랜잭션 모드의 동일한 최대 절전 모드 세션이 사용됩니다. 이렇게하면 db 레이어가 웹 레이어에 노출되어 안티 패턴이됩니다.

    OpenSessionInViewFilter는 http 요청에 대한 최대 절전 모드 세션을 바인드하는 서블릿 필터이며 모든 HTTP 요청에 대해 트랜잭션 및 비 트랜잭션 모드의 동일한 최대 절전 모드 세션이 사용됩니다. 이렇게하면 db 레이어가 웹 레이어에 노출되어 안티 패턴이됩니다.

    내 경험에 의하면 자바 객체를 변경하고자 할 때 코드를 디버그하기가 어렵고, 자바 객체가 데이터베이스에 반영되는 것을 원하지 않는다. 최대 절전 모드 세션은 항상 열려 있기 때문에 데이터베이스의 데이터를 플러시 할 것으로 예상됩니다.

    이것은 JS 기본 휴식 서비스가 중간에 서비스 레이어가없는 경우에만 사용해야합니다.

  4. ==============================

    4.OpenSessionInViewFilter의 일반적인 사용 패턴은 일부 Entity가 느리게로드되지만 뷰 렌더링 단계에서 뷰가이 엔터티의 일부 특성을 필요로하므로 초기에로드되지 않았으므로 데이터베이스에서이 데이터를 가져올 필요가 있습니다. 이제는 일반적으로 트랜잭션 경계 설정이 웹 애플리케이션의 서비스 계층에서 이루어 지므로 뷰 렌더링이 수행 될 때까지 뷰가 분리 된 엔티티와 함께 ​​작동하여 언로드 된 속성에 액세스 할 때 LazyInitializationException이 발생합니다.

    OpenSessionInViewFilter의 일반적인 사용 패턴은 일부 Entity가 느리게로드되지만 뷰 렌더링 단계에서 뷰가이 엔터티의 일부 특성을 필요로하므로 초기에로드되지 않았으므로 데이터베이스에서이 데이터를 가져올 필요가 있습니다. 이제는 일반적으로 트랜잭션 경계 설정이 웹 애플리케이션의 서비스 계층에서 이루어 지므로 뷰 렌더링이 수행 될 때까지 뷰가 분리 된 엔티티와 함께 ​​작동하여 언로드 된 속성에 액세스 할 때 LazyInitializationException이 발생합니다.

    이 URL https://developer.jboss.org/wiki/OpenSessionInView에서 :

    또는보기에 필요한 양의 데이터만으로 엔티티를로드하는 것을 고려해보십시오. 이것은 DTO 예측을 사용하여 수행 할 수 있습니다. 이 기사에서는 View Session In View 패턴을 사용할 때의 단점을 나열합니다. https://vladmihalcea.com/the-open-session-in-view-anti-pattern/

  5. from https://stackoverflow.com/questions/23877900/spring-opensessioninviewfilter-with-transactional-annotation by cc-by-sa and MIT license