我有一个用@Service注释的类正在实现javax.jms.MessageListener,在onMessage函数中我正在从存储库中检索一个对象,但是当我尝试预加载延迟加载的属性时,我得到“无法初始化代理 - 没有会话“例外。
我不想禁用延迟加载,因为页面实体在很多子实体中变得非常大,并且大多数时候我在处理页面对象时不需要这些子实体。
我在谷歌上发现并尝试了很多其他问题和解决方案,但似乎没有一个对我产生影响。
@Service
public class PageService implements MessageListener {
private PageRepository pageRepository;
public PageService(PageRepository pageRepository){
this.pageRepository = pageRepository;
}
@Override
@Transactional
public void onMessage(Message message) {
// Message handling etc etc..
int id = ....
Page page = pageRepository.findOne(id); // Page is retrieved successfully
page.InitializeAll(); // <--- Error happens here
// Build response message.
}
}
实体:
@Entity
public class Page {
....
@OrderBy("id ASC")
@OneToMany(mappedBy = "page", cascade = CascadeType.ALL)
public Set<Row> rows;
public void InitializeAll(){
Hibernate.initialize(this.rows); // <--- Error
rows.forEach(r -> r.InitializeAll());
}
}
页面存储库只是扩展了CrudRepository:
public interface PageRepository extends CrudRepository<Page, Integer>
在同一个包(/ folder)中的另一个文件中我有另一个用@Transactional注释的函数,里面有相同的函数调用,这里一切正常。
@MessageMapping("/page/{id}/request")
@SendToUser(value = "/queue/private", broadcast = false)
@Transactional
public initialPageMessage subscribeClient(@DestinationVariable("id") int pageId) {
initialPageMessage resp = new initialPageMessage();
resp.page = pageRepository.findOne(pageId);
resp.page.InitializeAll();
return resp;
}
TransactionManagerConfiguration:
@Configuration
@EnableTransactionManagement
public class TransactionManagerConfiguration {
private EntityManagerFactory entityManagerFactory;
private DataSource datasource;
public TransactionManagerConfiguration(EntityManagerFactory entityManagerFactory, DataSource datasource){
this.entityManagerFactory = entityManagerFactory;
this.datasource = datasource;
}
@Bean
public PlatformTransactionManager transactionManager(){
JpaTransactionManager tm = new JpaTransactionManager();
tm.setEntityManagerFactory(entityManagerFactory);
tm.setDataSource(datasource);
return tm;
}
}
堆栈跟踪
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: models.Page.rows, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:587) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:204) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:566) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:739) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at org.hibernate.Hibernate.initialize(Hibernate.java:65) ~[hibernate-core-5.0.11.Final.jar:5.0.11.Final]
at models.Page.InitializeAll(Page.java:31) ~[classes/:na]
at controllers.PageService.processMessage(PageService.java:93) ~[classes/:na]
at controllers.PageService.onMessage(PageService.java:75) ~[classes/:na]
at org.apache.activemq.ActiveMQMessageConsumer.dispatch(ActiveMQMessageConsumer.java:1401) ~[activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.ActiveMQSessionExecutor.dispatch(ActiveMQSessionExecutor.java:131) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.ActiveMQSessionExecutor.iterate(ActiveMQSessionExecutor.java:202) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.thread.PooledTaskRunner.runTask(PooledTaskRunner.java:133) [activemq-client-5.14.3.jar:5.14.3]
at org.apache.activemq.thread.PooledTaskRunner$1.run(PooledTaskRunner.java:48) [activemq-client-5.14.3.jar:5.14.3]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_40]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_40]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_40]
答案 0 :(得分:0)
一段时间后,我发现了问题,问题是从同一类内部调用了“ onMessage”方法。这样可以防止@Transactional代理(包装类)被调用。当我将@Transactional移到另一个类并从该类外部调用该函数时,它开始工作。