我对Hibernate如何处理一些事情有点困惑。我有一个仓库类,其中有一个方法使用了EntityManager中的persist
,因此它被添加到托管状态和持久性上下文。然后我有一个单独的方法,带有@Transactional
注解,仅调用flush
来手动提交EntityManager中当前的所有内容。
我这样做是因为我正在处理非常大的数据集,并且在存储它们之前已经必须完全或部分地迭代它们几次,所以我想通过 “将它们添加到EntityManager” 来保存迭代,而我已经在迭代它们并且它们已经完全构建,因此,我不必在以后的repository类中再次遍历完整列表,以便对每个实体调用persist
。
@ApplicationScoped
public class DataRepository {
private EntityManager entityManager;
private int totalAmountOfCachedData = 0;
@Inject
public DataRepository(EntityManager entityManager) {
this.entityManager = entityManager;
// This line does not change anything, with or without the same result
this.entityManager.setFlushMode(FlushModeType.COMMIT);
}
public int getTotalAmountOfCachedData() {
return totalAmountOfCachedData;
}
public void add(Data data) {
setReferences(data);
entityManager.persist(data);
totalAmountOfCachedData++;
}
@Transactional
public void commitCurrentDataToDb() {
entityManager.flush();
totalAmountOfCachedData = 0;
}
private void setReferences(Data data) {
//... running a few EntityManager.getReference here
}
}
我的理解是persist
实际上并不把实体保存到数据库中,只有当flush
被调用的时候,而且,据我所知,@Transactional
在方法周围 Package 了一个带有commit的自动事务,这是我不想在前一个中使用的。我在使用我的方法add()
时遇到了一个异常,询问是否要添加一个事务,但是如果我添加了一个事务,那么每次调用时都会自动将它们提交到数据库中,对吗?
javax.persistence.TransactionRequiredException: Transaction is not active, consider adding @Transactional to your method to automatically activate one.
at io.quarkus.hibernate.orm.runtime.session.TransactionScopedSession.persist(TransactionScopedSession.java:142)
at org.hibernate.engine.spi.SessionLazyDelegator.persist(SessionLazyDelegator.java:241)
at org.hibernate.Session_5b93bee577ae2f8d76647de04cfab36afbf52958_Synthetic_ClientProxy.persist(Unknown Source)
at com.test.entity.repository.DataRepository.add(DataRepository.java:36)
此外,我尝试将EntityManager的刷新模式设置为 “COMMIT” 而不是 “AUTO”,但没有效果。如何让add()
方法在不执行插入的情况下将实体添加到EntityManager中,并且只在使用commitCurrentDataToDb()
的单独调用中执行此操作?
1条答案
按热度按时间tcomlyy61#
我理解你的问题:您可能希望填充数据集,然后偶尔根据不同的用户请求刷新该数据。
这导致了扩展的持久性上下文......这在2007年和完全服务器端的应用程序(如JSF)中是一件事,而现在人们在Spring或任何其他无状态微服务世界中通常不会这样做。
我所看到的是-您正在尝试混合服务层(应用程序SPI)和持久层(应用程序实现)。
我建议您重新组织代码:从而引入有状态服务。
并且您的DataRepository应该实现2个方法:
有了这个,您将使用
DataService
进行操作,持久层将隐藏在DataService
客户端的某个位置。但是这种写入方式会使你的应用程序无法横向扩展,那么你最好考虑将
DataService
中的数据写入一些共享的内存存储,比如Hazelcast或Redis,而不是当前jvm-memory中的currentDataSet
列表,这样你就可以实现可扩展性。还有一个提示-〉尽管在持久性、SPI和API中拥有相同的数据是一个很好的承诺--但在实践中,它在原始用例中效果很好,对于更严重的情况,您应该为API、服务和持久性层以及相应的Map使用单独的数据模型。是的,这就是EE Java --从长远来看,它是值得的。作为第一个开始,我建议只使用2:API(与服务共享)和持久层数据模型。