英文:
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 = "releases_artists",
joinColumns = @JoinColumn(name = "release_id"),
inverseJoinColumns = @JoinColumn(name = "artist_id")
)
private Set<Artist> artists = new HashSet<>();
...
}
The class where the exception is thrown:
@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() <-- HERE
.stream()
.noneMatch(artist1 -> artist1.getDiscogsArtistId() != null)
) {
....
releaseRepository.save(releaseFromDb);
}
}
Parent abstract class:
@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); <--- HERE
} catch (Exception e) {
log.error("Error parse xml", e);
}
}
} catch (Exception e) {
log.error("Error parse xml", 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 上创建代理。这里有两个问题:
-
在这里,您并没有使用 bean,只是将
handle
作为同一类的方法。您必须注入一个 bean 并将其用作代理。 -
这个方法是
protected
的,但是它必须是public
的才能使@Transactional
起作用。
英文:
In order for @Transactional
to work, spring AOP needs to create a proxy over your bean. There are 2 issues here:
-
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. -
The method is
protected
, but it has to bepublic
for the@Transactional
to work.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论