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

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

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

问题

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

实体类:

public class Release extends AbstractEntity {

    ...

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
            name = "releases_artists",
            joinColumns = @JoinColumn(name = "release_id"),
            inverseJoinColumns = @JoinColumn(name = "artist_id")
    )
    private Set<Artist> artists = new HashSet<>();

    ...
}

异常抛出的类:

@Transactional
public class ReleaseXmlReader extends XmlReaderArrays<Release> {

    ...

    @Override
    protected void handle(Release release) {
        Release releaseFromDb = releaseRepository
                .findFirstByFonalId(release.getFonalId()).orElse(null);
        if (releaseFromDb != null) {
            for (Artist artist : release.getArtists()) {
                if (releaseFromDb.getArtists() <--- 在这里
                        .stream()
                        .noneMatch(artist1 -> artist1.getDiscogsArtistId() != null)
                ) {
        ....

        releaseRepository.save(releaseFromDb);
    }
}

抽象父类:

@Transactional
public abstract class XmlReaderArrays<T extends AbstractEntity> {

    ....

    public void parse() {
        try {
            XMLStreamReader reader = XMLInputFactory
                    .newInstance()
                    .createXMLStreamReader(inputStream);

            XmlMapper mapper = new XmlMapper();
            while (next(reader)) {
                limit--;
                try {
                    T obj = mapper.readValue(reader, type);
                    handle(obj); <--- 在这里
                } catch (Exception e) {
                    log.error("Error parse xml", e);
                }
            }

        } catch (Exception e) {
            log.error("Error parse xml", e);
        }
    }

    ...

}

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

英文:

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:

public class Release extends AbstractEntity {

    ...

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(
            name = &quot;releases_artists&quot;,
            joinColumns = @JoinColumn(name = &quot;release_id&quot;),
            inverseJoinColumns = @JoinColumn(name = &quot;artist_id&quot;)
    )
    private Set&lt;Artist&gt; artists = new HashSet&lt;&gt;();

    ...
}

The class where the exception is thrown:

@Transactional
public class ReleaseXmlReader extends XmlReaderArrays&lt;Release&gt; {

    ...

    @Override
    protected void handle(Release release) {
        Release releaseFromDb = releaseRepository
                .findFirstByFonalId(release.getFonalId()).orElse(null);
        if (releaseFromDb != null) {
            for (Artist artist : release.getArtists()) {
                if (releaseFromDb.getArtists() &lt;-- HERE
                        .stream()
                        .noneMatch(artist1 -&gt; artist1.getDiscogsArtistId() != null)
                ) {
        ....

             

        releaseRepository.save(releaseFromDb);
    }
}

Parent abstract class:

@Transactional
public abstract class XmlReaderArrays&lt;T extends AbstractEntity&gt; {

    ....

    public void parse() {
        try {
            XMLStreamReader reader = XMLInputFactory
                    .newInstance()
                    .createXMLStreamReader(inputStream);

            XmlMapper mapper = new XmlMapper();
            while (next(reader)) {
                limit--;
                try {
                    T obj = mapper.readValue(reader, type);
                    handle(obj); &lt;--- HERE
                } catch (Exception e) {
                    log.error(&quot;Error parse xml&quot;, e);
                }
            }

        } catch (Exception e) {
            log.error(&quot;Error parse xml&quot;, e);
        }
    }
  
    ...

}

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:

确定