2015-01-14 3 views
0

나는 Spring의 트랜잭션 관리에 대해 약간 새로운 것이다. 몇 가지 구성이 누락 된 것 같지만 해결할 수는 없습니다.Spring 4+ Hibernate 4 트랜잭션 관리 오류

오류는 내가 failed to lazily initialize a collection of role 예외입니다.

내 DAO에 스프링 데이터를 사용하고 있습니다. 또한, 나는 fagerType을 Eager로 설정하는 것에 대해서 알고 있지만 이것은 피하려고하는 것입니다.

DAO :

public interface CourseDao extends CrudRepository<CourseEntity, Long> { 
    CourseEntity findByName(String name); 
} 

서비스 :

@Service 
public class CourseMaterialSearchService { 
    private final CourseDao courseDao; 
    private final CourseMaterialEntityTransformer courseMaterialEntityTransformer; 

    @Autowired 
    public CourseMaterialSearchService(CourseDao courseDao, CourseMaterialEntityTransformer courseMaterialEntityTransformer) { 
     super(); 
     this.courseDao = courseDao; 
     this.courseMaterialEntityTransformer = courseMaterialEntityTransformer; 
    } 

    @Transactional 
    public List<CourseMaterial> findMaterialsFor(final Long courseId) { 
     final CourseEntity entity = courseDao.findOne(courseId); 
     final List<CourseMaterialEntity> materials = entity.getCourseMaterialEntityList(); 
     return courseMaterialEntityTransformer.transformEntities(materials); 
    } 
} 

그리고 내 응용 프로그램의 context.xml은 (물론 이것은 단지 관련 부분)입니다 :

<bean id="entityManagerFactory" 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="example" /> 
    <property name="dataSource" ref="exampleDataSource" /> 
    <property name="packagesToScan" value="com.example.example.**.repository" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="showSql" value="true" /> 
      <property name="generateDdl" value="true" /> 
     </bean> 
    </property> 
</bean> 
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
</bean> 

I을 CourseMaterialSearchServicefindMaterialsFor 메서드를 호출하면 예외가 발생합니다. 어떻게 해결해야합니까?

모든 의견을 환영합니다.

감사합니다.

스택 트레이스 :

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.example.course.repository.domain.CourseEntity.courseMaterialEntityList, could not initialize proxy - no Session 
org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575) 
org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214) 
org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554) 
org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142) 
org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:294) 
com.example.example.course.service.transform.CourseMaterialEntityTransformer.transformEntities(CourseMaterialEntityTransformer.java:15) 
com.example.example.course.service.CourseMaterialSearchService.findMaterialsFor(CourseMaterialSearchService.java:29) 

CourseMaterialEntityTransformer :

public class CourseMaterialEntityTransformer { 
     public List<CourseMaterial> transformEntities(final Iterable<CourseMaterialEntity> entities) { 
      final List<CourseMaterial> result = new ArrayList<>(); 
      for (final CourseMaterialEntity entity : entities) { 
       result.add(transformEntity(entity)); 
      } 
      return result; 
     } 

    public CourseMaterial transformEntity(final CourseMaterialEntity entity) { 
     final CourseMaterial result = new CourseMaterial(); 
     result.setId(entity.getId()); 
     result.setName(entity.getName()); 
     result.setCourseName(entity.getCourseEntity().getName()); 
     result.setCurrentFileName(entity.getCurrentFileName()); 
     result.setOriginalFileName(entity.getOriginalFileName()); 
     result.setCategory(entity.getMaterialCategoryEntity().getName()); 
     result.setUploader(entity.getUserEntity().getName()); 
     return result; 
    } 
} 

com.example.example.course.service.transform.CourseMaterialEntityTransformer.transformEntities(CourseMaterialEntityTransformer.java:15) :

for (final CourseMaterialEntity entity : entities) { 

CourseEntity :

@Entity(name = "courses") 
public class CourseEntity { 
    @Id 
    @GeneratedValue 
    private Long id; 

    private String name; 

    @OneToMany(mappedBy = "courseEntity") 
    private List<CourseMaterialEntity> courseMaterialEntityList; 

    public Long getId() { 
     return id; 
    } 

    public void setId(final Long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(final String name) { 
     this.name = name; 
    } 

    public List<CourseMaterialEntity> getCourseMaterialEntityList() { 
     return courseMaterialEntityList; 
    } 

    public void setCourseMaterialEntityList(final List<CourseMaterialEntity> courseMaterialEntityList) { 
     this.courseMaterialEntityList = courseMaterialEntityList; 
    } 

} 
+0

stacktrace log 후 –

+0

내 질문이 업데이트되었습니다. – galovics

+0

plz 도메인 개체도 게시하십시오. –

답변

1

봄은 AOP를 사용하여 트랜잭션을 적용합니다. Bean의 AOP는 동일한 응용 프로그램 컨텍스트의 Bean에만 적용됩니다.

귀하의 application-context.xml<tx:annotation-driven />이 있으며 여기에는 ContextLoaderListener이 있습니다. 이 파일에는 <context:component-scan />이 포함되어있어 @Service을 감지합니다.

DispatcherServlet에 의해로드 된 파일에 동일한 <context:component-scan />이 있거나 최소한 @Service이 검색되면 AOP가 적용되지 않는이 서비스의 다른 인스턴스가 생성됩니다.

은 일반적인 규칙의 - 엄지 손가락으로 당신은 모든 것을로드 할하지만 당신의 DispatcherServletContextLoaderListener 만 웹과 관련된 일에 @Controllers (뷰 리졸버, @Controllers).

context depended scan-component filter을 참조하십시오.

0

트랜잭션 외부의 지연로드 속성에 액세스하려고합니다. 그런 다음 객체는 트랜잭션 외부에 있으므로 EntityManager (데이터베이스)와 연결되지 않으므로 지연로드 속성을 가져올 수 없습니다.

+0

흠, 그래, 어떻게 해결할 수 있니? findMaterialsFor 메서드에서 entity.getCourseMaterialEntityList(). size()를 호출하면 올바르게 작동합니까? – galovics

+0

그는 메소드 상단에'@ Transactional'을 가지고 있으므로'@ Transactional' 범위에 있어야합니다. – Mior

+0

트랜잭션 관리자가 주석을 처리하도록 올바르게 설정되어있는 경우에만. 오류 메시지는 그것이 무엇인지, 그리고 그것이 내 답변에서 제공 한 설명입니다. – Tobb

0

기본적으로 컬렉션은 지연로드됩니다. 당신은 당신의 코드를 아래 대체 할 수

@OneToMany(mappedBy = "courseEntity") 
private List<CourseMaterialEntity> courseMaterialEntityList; 

으로 :

@OneToMany(fetch = FetchType.EAGER, mappedBy = "courseEntity", cascade = CascadeType.ALL) 
private List<CourseMaterialEntity> courseMaterialEntityList; 
+0

나는 그것을 열심히 가져오고 싶지 않다. 내가 피하려고하는 것을 말한다. – galovics

0

당신은 당신이 시도 그렇게 할 때 유형 게으른 가져 @OneToMany(mappedBy = "courseEntity", fetch = FetchType.EAGER, cascade = CascadeType.ALL)

기본에 @OneToMany(mappedBy = "courseEntity")을 변경하고 컬렉션에 액세스해야 데이터베이스에서로드되지 않았습니다.

+0

나는 열심히 가져오고 싶지 않다. – galovics

+0

반드시 열심히 가져올 필요는 없습니다. 문제는 트랜잭션에서 엔터티를로드하려고 시도하는 것입니다. – Mior

+0

'CourseMaterialEntity'는 어떻게 생겼습니까? –

관련 문제