복붙노트

[SPRING] Hibernate / Spring : @Transactional on Service 메소드로 자식 컬렉션을 검색하기 전에 세션이 여전히 닫혔다.

SPRING

Hibernate / Spring : @Transactional on Service 메소드로 자식 컬렉션을 검색하기 전에 세션이 여전히 닫혔다.

Hello Spring / Hibernate Gurus!

이런 시간에 나는 내 가장 친한 친구가되고 싶다. 나는 최대 절전 모드 3.6.1을 사용하는 프로젝트에서 일하고있다. 세션과 스프링 3.0.5를 사용하는 최종 JPA 구현. 메이븐과 릴리스. 메이븐 프로젝트는 3 모듈 모델 모듈, 서비스 모듈 및 webapp 모듈.

여기서 모델 applicationContext의 스 니펫입니다.

       <!-- Transaction Management    -->
<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- Model -->
<bean id="genericDAO" class="com.blabla.blabla.model.dao.hibernate.HibernateGenericDAOImpl" abstract="true">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>



<bean id="content" class="com.blabla.blabla.model.ContentImpl" scope="prototype" />

<bean id="contentDAO" class="com.blabla.blabla.model.dao.hibernate.ContentDAOImpl" parent="genericDAO">
    <constructor-arg>
        <value>com.blabla.blabla.model.ContentImpl</value>
    </constructor-arg>
</bean>

나도 나에게 악몽을주는 릴레이션에 매핑의 스 니펫 (snippet)을 붙여서 모든 것을 여기에 버리지 않을 것이다 :

//ContentImpl
@Id
@Column(name = "CONTENT_ID")
private Long ID;
@Version
@Column(name = "OBJ_VERSION")
private int version = 0;
//.... other properties

@OneToMany(targetEntity = ContentImageImpl.class,cascade = {CascadeType.ALL},orphanRemoval = true)
@JoinColumn(name = "CONTENT_ID", referencedColumnName = "CONTENT_ID")
private Set<ContentImage> images = new HashSet<ContentImage>();

//ContentImageImpl
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "CONTENT_IMAGE_ID")
private Long ID;

@Column(name = "PATH")
private String path;

@Column(name ="IS_DEFAULT")
private Boolean isDefault;
//no other relations


//ContentServiceImpl
 public class ContentServiceImpl implements ContentService {
//wired from application context
private ContentDAO contentDao;
private static Logger logger = Logger.getLogger(ContentServiceImpl.class);

@Transactional
public List<Content> getContentsbyCategoryID(Long categoryId) {
    return getContentDao().getbyCategoryID(categoryId);
}


@Transactional
public List<Content> getContentsWithImagesbyCategoryID(Long categoryId) {
//return getContentDao().getbyCategoryID(categoryId);
    return getContentDao().getWithImagesbyCategoryID(categoryId);



//ContentDAOImpl
 public List<Content> getbyCategoryID(Long category_id) {
    Category cat = modelManager.createCategory();
    cat.setID(category_id);
    logger.info("calling  getbyCategoryID");
    logger.debug(category_id);
    List<Content> session =  this.getSessionFactory().getCurrentSession().createCriteria(this.getPersistentClass())
            .add(Restrictions.eq("category",(CategoryImpl)cat))
            .setProjection(Projections.distinct(Projections.id()))
            .list();
    logger.debug(session);
    return session;
}

그래서 평가할 때 contentService.getContentbyCategoryId (longid) 그것은 던졌습니다.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of  role: com.bla.bla.model.ContentImpl.contentFiles, no session or session was closed

정말 귀찮다. 내가 한 유일한 임시 수정은이 연관성을 열심히 가져 오는 것과 일치하지 않는다는 것을 확인하는 것이다. 아무 것도 열리지 않을 때 새로운 세션을 열도록 서비스 메소드 상단에 @transactional을 넣을 것이라고 생각했다.

이것을 읽어 주셔서 감사드립니다.

해결법

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

    1.보기를 렌더링 할 때 이런 현상이 발생합니까? 그렇다면 Spring의 OpenSessionInViewFilter 사용을 고려할 수도 있습니다. 이것은 요청의 전체 처리를 위해 세션을 스레드에 바인드합니다. JPA를 사용하는 경우 OpenEntityManagerInViewFilter를 사용할 수 있습니다.

    보기를 렌더링 할 때 이런 현상이 발생합니까? 그렇다면 Spring의 OpenSessionInViewFilter 사용을 고려할 수도 있습니다. 이것은 요청의 전체 처리를 위해 세션을 스레드에 바인드합니다. JPA를 사용하는 경우 OpenEntityManagerInViewFilter를 사용할 수 있습니다.

    귀하의 web.xml에서 :

    <filter>
        <filter-name>OpenSessionInViewFilter</filter-name>
        <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
        <init-param>
            <param-name>sessionFactoryBeanName</param-name>
            <param-value>sessionFactory</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>OpenSessionInViewFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
  2. ==============================

    2.트랜잭션의 범위 (따라서 세션)는 getContentsbyCategoryID () 메소드 주위에서만 발생합니다. 일단 세션에서 돌아 오면 트랜잭션이 커밋되고 세션이 닫힙니다. 정확히 어디에서 예외가 발생합니까? getContentsbyCategoryID () 내부의 list () 연산에 있습니까? 또는 실제로 getContentsbyCategoryID ()에서 돌아와 코드의 다른 곳에서 게으른 모음집에 액세스하려고 한 후에입니까? 이 경우, 당신은

    트랜잭션의 범위 (따라서 세션)는 getContentsbyCategoryID () 메소드 주위에서만 발생합니다. 일단 세션에서 돌아 오면 트랜잭션이 커밋되고 세션이 닫힙니다. 정확히 어디에서 예외가 발생합니까? getContentsbyCategoryID () 내부의 list () 연산에 있습니까? 또는 실제로 getContentsbyCategoryID ()에서 돌아와 코드의 다른 곳에서 게으른 모음집에 액세스하려고 한 후에입니까? 이 경우, 당신은

  3. from https://stackoverflow.com/questions/9274949/hibernate-spring-session-still-closed-before-retrieval-of-child-collection-even by cc-by-sa and MIT license