繁体   English   中英

LazyInitializationException和@Transactional无法正常工作

[英]LazyInitializationException and @Transactional not working

我使用的Spring 3.2.9具有多层体系结构设计,可分为3个模块,即Web,服务,存储库。 在存储库中,我定义了一个通用DAO类,该类由其他特定于实体的DAO类继承。

问题是,当我尝试从服务层延迟获取我的实体的集合时,总是会得到LazyInitializationException。 我尝试将@Transactional放在我的服务类上,但是似乎不起作用。 仅当我立即在DAO类方法中初始化所有惰性集合时(并且仅当我使用@Transactional注释DAO类时),我才能避免出现异常,但是我只想在业务逻辑中需要这些集合时才获取这些集合,而不是全部提前。

奇怪的是,@ Transactional仅在DAO层中起作用,而在应使用它的Service层中不起作用。 我找到了解决此问题的几种方法,但我有兴趣真正地理解和解决此问题,不仅使make代码起作用。

资料库模块:

@Repository
public abstract class GenericDao<T> {

    protected Class<T> entityClass;

    @PersistenceContext
    protected EntityManager entityManager;

    .........

    public T findById(long id) {
        T entity = entityManager.find(entityClass, id);
        if (entity == null) {
            throw new EntityNotFoundException(entityClass.getSimpleName(), id);
        }

        return entity;
    }
}

我在服务模块MODULE中的服务类别:

@Service
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    public UserServiceImpl(UserDao userDao) {
        this.userDao = userDao;
    }

    @Transactional(readOnly = true)
    @Override
    public UserDto getUserById(long id) {
        User user = userDao.findById(id);

        return new UserDto(user);
    }

DTO构造函数尝试访问user.getTeams(),然后发生异常。 取而代之的是,应该使用对数据库的附加查询来获取集合。

组态:

存储库配置:......其他一些配置,例如数据源...

<!--EntityManagerFactory-->
<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceXmlLocation" value="classpath:./META-INF/persistence.xml"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.dialect" value="${hibernate_dialect}"/>
            <entry key="hibernate.hbm2ddl.auto" value="${hibernate_Hbm2ddlAuto}"/>
            <entry key="hibernate.show_sql" value="${hibernate_showSql}"/>
            <entry key="hibernate.format_sql" value="${hibernate_formatSql}"/>
        </map>
    </property>
</bean>

persistence.xml:

<persistence-unit name="persistenceUnit">
    ...other classes..
    <class>com.example.entity.User</class>
    <exclude-unlisted-classes>true</exclude-unlisted-classes>
    <properties>
    </properties>
</persistence-unit>

服务配置:

<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/>

<tx:annotation-driven/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

用户和他或她的团队之间的@OneToMany关联看起来像是延迟加载的。 当您将它们分配给Dto时,它仍然是代理而不是实际集合。 在此处放置一个断点,并在调试模式下查看它。 请记住任何要求(请一个团队或其规模使它保持活力)。 一种方法是在查询中获取它们,但是

entityManager.find(entityClass, id)

没有选择。 您可以使用

Hibernate.initialize(user.getTeams())

经过几天的头痛,找到了答案。 我不得不移动:

<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/>
<tx:annotation-driven/>

从repositoryConfiguration.xml到dispatcher-servlet.xml,因为那是父Spring上下文。

谢谢您的帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM