首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring 4+ Hibernate 4事务管理错误

Spring 4+ Hibernate 4事务管理错误
EN

Stack Overflow用户
提问于 2015-01-14 09:09:09
回答 4查看 580关注 0票数 0

我对Spring的事务管理有点陌生。我想我错过了一些配置,但我无法处理。

错误是我得到了failed to lazily initialize a collection of role异常。

我使用Spring数据作为我的DAO。另外,我知道如何将fetchType设置为急切,但这正是我想要避免的。

DAO:

代码语言:javascript
复制
public interface CourseDao extends CrudRepository<CourseEntity, Long> {
    CourseEntity findByName(String name);
}

服务:

代码语言:javascript
复制
@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是(当然,这只是相关的部分):

代码语言:javascript
复制
<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>

当我在findMaterialsFor中调用CourseMaterialSearchService方法时,会出现异常。我该怎么解决这个问题?

如有任何建议,将不胜感激。

谢谢你们。

堆栈跟踪:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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)

代码语言:javascript
复制
for (final CourseMaterialEntity entity : entities) {

CourseEntity:

代码语言:javascript
复制
@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;
    }

}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-01-14 09:38:58

Spring使用AOP应用事务。beans上的AOP仅应用于同一应用程序上下文中的bean。

您的application-context.xml中有一个application-context.xml,它由ContextLoaderListener加载。此文件包含一个检测<context:component-scan />@Service

但是,如果在由<context:component-scan />加载的文件中也有相同的DispatcherServlet,或者至少如果检测到相同的@Service,则会导致该服务的另一个实例不被应用。

作为一个普遍的经验法则,您希望在您的ContextLoaderListener中加载除ContextLoaderListener之外的所有内容,而只在您的DispatcherServlet中加载与web相关的内容(视图解析器、@Controllers)。

context depended scan-component filter

票数 1
EN

Stack Overflow用户

发布于 2015-01-14 09:18:02

您正在尝试访问事务之外的延迟加载属性。然后,该对象与EntityManager (数据库)没有连接,因为它位于事务之外,因此无法获取延迟加载的属性。

票数 0
EN

Stack Overflow用户

发布于 2015-01-14 09:19:52

默认情况下,集合是延迟加载的。您可以在代码下面替换:

代码语言:javascript
复制
@OneToMany(mappedBy = "courseEntity")
private List<CourseMaterialEntity> courseMaterialEntityList;

有:

代码语言:javascript
复制
@OneToMany(fetch = FetchType.EAGER, mappedBy = "courseEntity", cascade = CascadeType.ALL)
private List<CourseMaterialEntity> courseMaterialEntityList;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27939205

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档