gpt4 book ai didi

java - 如何使用多个@Transactional 注解的方法?

转载 作者:行者123 更新时间:2023-12-01 17:27:17 24 4
gpt4 key购买 nike

我有一个 Spring-boot 项目,其中有一个带有 2 @Transactional 的服务 bean带注释的方法。

这些方法执行只读 JPA( hibernate )操作,以使用 JPA 存储库和实体中的延迟加载 getter 从 HSQL 文件数据库获取数据。

我还有一个处理命令的 cli bean(使用 PicoCLI)。我尝试从这些命令之一调用 @Transactional带注释的方法,但在执行第二个方法时出现以下错误:

org.hibernate.LazyInitializationException - could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:602)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:217)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:581)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:148)
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:188)
at java.util.Spliterators$IteratorSpliterator.estimateSize(Spliterators.java:1821)
at java.util.Spliterator.getExactSizeIfKnown(Spliterator.java:408)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
at <mypackage>.SomeImpl.getThings(SomeImpl.java:<linenr>)
...

如果我标记同时调用 @Transactional 的方法带 @Transactional 注释的方法代码本身似乎可以工作(因为我猜现在只有 1 个顶级事务?)。

我只是想找出为什么我无法在单个 session 中启动多个事务,或者为什么第二个事务在没有事务的情况下不启动新 session 。

所以我的问题是:

  • 这是否与 hibernate 如何启动 session 、事务如何关闭 session 或与 HSQL 数据库相关的任何内容有关?
  • 添加包容性事务是解决问题的正确方法吗或者这只是对抗症状?
  • 能够使用多个 @Transactional 的最佳方式是什么?来自一种方法的带注释的方法?

编辑:我想澄清的是,我不会公开事务方法之外的实体,因此从表面上看,在我看来,这两种事务方法应该彼此独立工作。

编辑2:更多说明:事务方法需要在 API 中可用,并且 API 的用户应该能够调用多个这些事务方法,而无需使用事务注释,也无需获取 LazyInitializationException

API:

public interface SomeApi {
List<String> getSomeList();
List<Something> getThings(String somethingGroupName);
}

实现:

public class SomeImpl implements SomeApi {

@Transactional
public List<String> getSomeList() {
return ...; //Do jpa stuff to get the list
}

@Transactional
public List<Something> getThings(String somethingGroupName) {
return ...; //Do other jpa stuff to get the result from the group name
}
}

第三方的使用(他们可能不知道什么是事务性):

public someMethod(String somethingGroupName) {
...

SomeApi someApi = ...; // Get an implementation of the api in some way

List<String> someList = someApi.someList();
if (someList.contains(somethingGroupName) {
System.out.println(someApi.getThings(somethingGroupName));
}

...
}

最佳答案

交易结束后,您似乎正在从实体访问一些未初始化的数据。在这种情况下,持久性提供程序可能会抛出延迟初始化异常。

如果您需要检索一些未随实体立即加载的信息,您可以使用以下两种策略之一:

  • 也使用 @Transactional 注解来注解调用方法,就像您所做的那样:它不会为每次调用启动一个新事务,而是使打开的事务处于 Activity 状态,直到您的调用方法结束,从而避免异常;或
  • 使用 JOIN FETCH JPQL 习惯用法让被调用的方法立即加载所需的字段。

事务边界需要对您的场景进行一些分析。请阅读this answer并寻找更好的书籍或教程来掌握它。也许只有您才能恰本地定义您的要求。

关于java - 如何使用多个@Transactional 注解的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61194584/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com