我使用Spring 3.2.9将多层架构设计分解为3个模块web,service,repository。在存储库中,我定义了一个通用的DAO类,它由其他实体特定的DAO类继承。
问题是当我尝试从服务层延迟获取我的实体的集合时,我总是得到LazyInitializationException。我已经尝试将@Transactional放在我的服务类上,但它似乎不起作用。如果我在DAO类方法中立即初始化所有延迟集合(并且仅当我使用@Transactional注释DAO类)时,我才能避免异常,但我只想在商业逻辑中需要它们时获取这些集合,而不是全部提前。
奇怪的是,@ Transactal仅适用于DAO层,但不适用于服务层,应该使用它。我找到了几种方法来解决这个问题,但我有兴趣真的低估并解决这个问题,而且不仅仅是让make代码工作。
repository MODULE:
@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(),然后发生异常。取而代之的是,应该使用DB的附加查询来提取集合。
配置:
存储库配置: ......一些其他配置,如数据源...
<!--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>
答案 0 :(得分:0)
看起来用户和他或她的团队之间的@OneToMany关联是懒惰加载的。当您将它们分配给Dto时,它仍然是代理不是真正的集合。在那里放置一个断点并在调试模式下查看它。请记住任何请求(获得一个团队或其规模使其活着)。一种方法是在查询中获取它们,但
entityManager.find(entityClass, id)
没有选项。你可以使用
Hibernate.initialize(user.getTeams())
答案 1 :(得分:0)
头痛几天后找到了答案。 我不得不搬家:
<import resource="classpath*:META-INF/repositoryApplicationContext.xml"/>
<tx:annotation-driven/>
从repositoryConfiguration.xml到dispatcher-servlet.xml,因为那是父Spring上下文。
感谢您的帮助。