2013-06-25 5 views
0

최대 절전 모드. @Repositoy 및 일부 Controller-Class로 주석이 달린 DAO 클래스가 있습니다. 내 컨트롤러에서 DAO 메소드 중 하나를 호출하여 엔티티를로드 한 다음 엔티티를 가져오고 난 후 첫 번째로드 된 엔티티의 필드에 저장된 다른 엔티티를 가져 오려고합니다. 하지만 그때 봄은 이미 세션을 닫았으며 게으른로드는 더 이상 가능하지 않습니다. 게으른 로딩 JPA 봄 엔티티와 내가 JPA와 최대 절전 모드와 스프링을 사용하고

내 db.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:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    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.0.xsd 
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd 
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd 
     http://www.springframework.org/schema/data/jpa 
     http://www.springframework.org/schema/data/jpa/spring-jpa.xsd" default-autowire="byName"> 

    <!-- Scans within the base package of the application for @Components to configure as beans --> 
    <bean id="placeholderConfig" 
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="location" value="classpath:db.properties" /> 
    </bean> 
    <tx:annotation-driven transaction-manager="transactionManager"/> 
    <!-- <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="jpaVendorAdapter" /> 
    </bean> --> 
    <bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="showSql" value="true" /> 
       <property name="generateDdl" value="true" /> 
       <property name="databasePlatform" value="${db.dialect}" /> 
      </bean> 
     </property>  
    </bean> 

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" 
     destroy-method="close"> 
     <property name="driverClassName" value="${db.driver}" /> 
     <property name="url" value="${db.url}" /> 
     <property name="username" value="${db.username}" /> 
     <property name="password" value="${db.password}" /> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" /> 
</beans> 

다음과 같이 다오의 방법은 주석이 :

@Transactional(readOnly = true, propagation=Propagation.REQUIRED) 

이 지금은 같은 것을 할 싶어 :

@Controller 
public class HomeController{ 

    @Autowired 
    private UserDao userDao; 

    @RequestMapping(value = "/", method = RequestMethod.GET) 
    public ResponseEntity<String> home(){ 
     ... 
     User user = userDao.findUser(id); 
     Set<Order> orders = user.getOrders(); 
     ... 
    String myResult = ...; 
    return jsonService.generateResponse(myResult); 
    } 

} 

@Repository 
public class UserDao{ 

    @PersistenceContext 
    private EntityManager entityManager; 

    public User findUser(Integer id){ 
     return entityManager.find(User.class, id); 
    } 
} 

순서 집합은 게으른로드되어야하지만 다음과 같은 예외가 발생합니다 : org.springframework.web.util.NestedServletExcep 요청 처리가 실패했습니다. 중첩 예외는 org.hibernate.LazyInitializationException : 지연 컬렉션을 지연 초기화하지 못했습니다 : ..., 세션이나 세션이 닫혀지지 않았습니다.

근본 원인 : org.hibernate.LazyInitializationException : 지연 컬렉션을 지연 생성하지 못했습니다 : ..., 세션이나 세션이 닫혀지지 않았습니다.

컨트롤러 wirt @Transactional에서 주석을 달고 db.xml의 주석 중심 속성에서 mode = "aspectj"를 설정하려고했지만 아무것도 작동하지 않았습니다. 사용자의 주문을 게으른로드 할 수있는 방법이 있습니까? 기대 부탁드립니다 어떤 도움

!

답변

5

당신은 웹보기에서 세션을 얻기 위해 특수 필터를 사용할 수 있습니다.

  • 필터는
  • 필터는 EntityManager를 여는 서블릿 요청을 차단하고, 현재의 thread
  • 웹에 바인드 다음과 같이

    <filter> 
        <filter-name>jpaFilter</filter-name> 
        <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class> 
    </filter> 
    <filter-mapping> 
        <filter-name>jpaFilter</filter-name> 
        <url-pattern>/*</url-pattern> 
    </filter-mapping> 
    

    필터가 작동 당신의 web.xml에 추가 컨트롤러가 호출 됨

  • 웹 컨트롤러 호출 서비스
  • 트랜잭션 인터셉터는 새로운 트랜잭션은 다음
  • 트랜잭션 인터셉터는 EntityManager를 다음 트랜잭션을
  • 웹을 저지른 플러시 반환 EntityManager의 몇 가지 물건을 수행, 스레드 바인딩 EntityManager를 검색하고
  • 서비스가 호출되는 거래 에게 바인드 컨트롤러는
  • 보기
  • 필터는 EntityManager를 닫 내장되어 반환하고 는 현재 스레드
  • ,691에서 바인딩 해제, 보기를 준비
+0

JSON이 반환됩니다. 따라서 문제는로드 지연 엔티티를 시도하는 웹보기가 아니어야합니다. 오류는 컨트롤 메서드에서 발생합니다. – mheck

+0

스프링 쉼과 JSON을 위해 이것을 사용하고 있으며 매력처럼 작동합니다. 약간의 성능 과부하 (내 설명 참조)가 있지만 작동해야합니다. 그냥 시도해보십시오 :) – zacheusz

+0

정말 작동합니다. @Transactional 어노테이션을 어디에 넣어야합니까? DAO 또는 컨트롤러? 나는 성능이 훨씬 나아야 항상 열망하는 엔티티를 가져와야한다고 생각한다. 그렇게 생각하지 않니? – mheck