Hibernate:在使用@Transactional的情况下,延迟初始化集合角色时出现了失败。

huangapple go评论97阅读模式
英文:

Hibirnate: failed to lazily initialize a collection of role with @Transactional

问题

我遇到了这样一个问题:当我惰性加载集合时,它会抛出异常。我使用了 Transactional 注解,以及 Hibernate.initialize,但在加载集合时仍然出错。只有使用 EAGER 可以解决,但这会导致开销过大。

实体类:

  1. public class Release extends AbstractEntity {
  2. ...
  3. @ManyToMany(fetch = FetchType.LAZY)
  4. @JoinTable(
  5. name = "releases_artists",
  6. joinColumns = @JoinColumn(name = "release_id"),
  7. inverseJoinColumns = @JoinColumn(name = "artist_id")
  8. )
  9. private Set<Artist> artists = new HashSet<>();
  10. ...
  11. }

异常抛出的类:

  1. @Transactional
  2. public class ReleaseXmlReader extends XmlReaderArrays<Release> {
  3. ...
  4. @Override
  5. protected void handle(Release release) {
  6. Release releaseFromDb = releaseRepository
  7. .findFirstByFonalId(release.getFonalId()).orElse(null);
  8. if (releaseFromDb != null) {
  9. for (Artist artist : release.getArtists()) {
  10. if (releaseFromDb.getArtists() <--- 在这里
  11. .stream()
  12. .noneMatch(artist1 -> artist1.getDiscogsArtistId() != null)
  13. ) {
  14. ....
  15. releaseRepository.save(releaseFromDb);
  16. }
  17. }

抽象父类:

  1. @Transactional
  2. public abstract class XmlReaderArrays<T extends AbstractEntity> {
  3. ....
  4. public void parse() {
  5. try {
  6. XMLStreamReader reader = XMLInputFactory
  7. .newInstance()
  8. .createXMLStreamReader(inputStream);
  9. XmlMapper mapper = new XmlMapper();
  10. while (next(reader)) {
  11. limit--;
  12. try {
  13. T obj = mapper.readValue(reader, type);
  14. handle(obj); <--- 在这里
  15. } catch (Exception e) {
  16. log.error("Error parse xml", e);
  17. }
  18. }
  19. } catch (Exception e) {
  20. log.error("Error parse xml", e);
  21. }
  22. }
  23. ...
  24. }

我尝试过只在父类或者只在子类中使用注解。我还尝试将注解放在方法上,但没有帮助。

英文:

I have such a problem: when I load the collection lazily, it throws an exception. I used the Transactional annotation, Hibernate.initialize, but it still gives an error when loading the collection. Only EAGER helps, but it will be too expensive to use.

Entity:

  1. public class Release extends AbstractEntity {
  2. ...
  3. @ManyToMany(fetch = FetchType.LAZY)
  4. @JoinTable(
  5. name = &quot;releases_artists&quot;,
  6. joinColumns = @JoinColumn(name = &quot;release_id&quot;),
  7. inverseJoinColumns = @JoinColumn(name = &quot;artist_id&quot;)
  8. )
  9. private Set&lt;Artist&gt; artists = new HashSet&lt;&gt;();
  10. ...
  11. }

The class where the exception is thrown:

  1. @Transactional
  2. public class ReleaseXmlReader extends XmlReaderArrays&lt;Release&gt; {
  3. ...
  4. @Override
  5. protected void handle(Release release) {
  6. Release releaseFromDb = releaseRepository
  7. .findFirstByFonalId(release.getFonalId()).orElse(null);
  8. if (releaseFromDb != null) {
  9. for (Artist artist : release.getArtists()) {
  10. if (releaseFromDb.getArtists() &lt;-- HERE
  11. .stream()
  12. .noneMatch(artist1 -&gt; artist1.getDiscogsArtistId() != null)
  13. ) {
  14. ....
  15. releaseRepository.save(releaseFromDb);
  16. }
  17. }

Parent abstract class:

  1. @Transactional
  2. public abstract class XmlReaderArrays&lt;T extends AbstractEntity&gt; {
  3. ....
  4. public void parse() {
  5. try {
  6. XMLStreamReader reader = XMLInputFactory
  7. .newInstance()
  8. .createXMLStreamReader(inputStream);
  9. XmlMapper mapper = new XmlMapper();
  10. while (next(reader)) {
  11. limit--;
  12. try {
  13. T obj = mapper.readValue(reader, type);
  14. handle(obj); &lt;--- HERE
  15. } catch (Exception e) {
  16. log.error(&quot;Error parse xml&quot;, e);
  17. }
  18. }
  19. } catch (Exception e) {
  20. log.error(&quot;Error parse xml&quot;, e);
  21. }
  22. }
  23. ...
  24. }

I tried to match annotation only with the parent class or only with the inheritor. I also tried to put the annotation on the methods, but it did not help.

答案1

得分: 1

为了使 @Transactional 起作用,Spring AOP 需要在您的 bean 上创建代理。这里有两个问题:

  1. 在这里,您并没有使用 bean,只是将 handle 作为同一类的方法。您必须注入一个 bean 并将其用作代理。

  2. 这个方法是 protected 的,但是它必须是 public 的才能使 @Transactional 起作用。

英文:

In order for @Transactional to work, spring AOP needs to create a proxy over your bean. There are 2 issues here:

  1. Here you're not using bean, just using handle as the method of the same class. You would have to inject a bean to use it as proxy.

  2. The method is protected, but it has to be public for the @Transactional to work.

huangapple
  • 本文由 发表于 2020年10月16日 15:15:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/64384557.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定