Java Hibernate:从不同事务访问创建的实体
我有相当复杂的方法,它们在执行过程中创建并使用不同的实体。例如,我创建了一些图像,然后将它们添加到文章中:Java Hibernate:从不同事务访问创建的实体,java,mysql,hibernate,Java,Mysql,Hibernate,我有相当复杂的方法,它们在执行过程中创建并使用不同的实体。例如,我创建了一些图像,然后将它们添加到文章中: @Transactional public void createArticle() { List<Image> images = ... for (int i = 0; i < 10; i++) { // creating some new images, method annotated @Transactional images.ad
@Transactional
public void createArticle() {
List<Image> images = ...
for (int i = 0; i < 10; i++) {
// creating some new images, method annotated @Transactional
images.add(repository.createImage(...));
}
Article article = getArticle();
article.addImages(images);
em.merge(article);
}
@Transactional
公共物品{
列表图像=。。。
对于(int i=0;i您可以尝试将数据源上的事务隔离设置为READ_UNCOMMITTED,但这可能会导致不一致,因此通常不建议这样做。考虑利用Hibernate级联功能一次性持久化对象树,同时最小化数据库锁定:
@Entity
public class Article {
@OneToMany(cascade=CascadeType.MERGE)
private List<Images> images;
}
@Transactional
public void createArticle() {
//images created as Java objects in memory, no DAOs called yet
List<Image> images = ...
Article article = getArticle();
article.addImages(images);
// cascading will save the article AND the images
em.merge(article);
}
我的最佳猜测是,您的事务隔离级别是可序列化的。这就是为什么DB会在整个事务期间锁定受影响的表。
如果是这种情况,请将级别更改为READ_COMMITTED.Hibernate(或任何JPA提供程序)可以很好地使用此版本。
除非您显式调用entityManager.lock(someEntity,LockModeType.SomeLockType)),否则它不会锁定任何内容。
此外,当您选择事务边界时,首先考虑原子性是一个原子工作单元,它必须是事务性的,为了“优化”而将它分解成更小的事务是错误的。我尝试使用这个,但是异常说它在Hibernate中是不允许的。无论如何,我不想读未提交的,我宁愿提交更改并使用它们。广告1:这是这可能是一个很好的解决方案,但我忘了提到一个事实,那就是在创建图像时,我需要知道它们的ID,这样才能将它们保存到磁盘上。我想除非我开始用哈希值保存它们,否则DB调用将是不可避免的。但是我仍然认为,如果对DB的所有调用都是分开的,那么它会起作用。广告2:我确实尝试过这个,但这是不可能的ads tojavax.persistence.EntityNotFoundException
就好像这两个事务彼此都不知道一样。尝试使用@SequenceGenerator在不阻塞的情况下生成映像Id。这将通过调用数据库序列来创建Id,但不会触发实体本身的插入tellyhttp://www.java2s.com/Tutorial/Java/0355__JPA/UseSequenceGenerator.htm。就像您拥有ID并且可以在提交图像插入之前使用它一样,您如何获得EntityNotFoundException?如果您可以发布stacktrace,但这意味着对一个ID在数据库中不再/尚未存在的实体调用了refresh、lock或getReference。您可以发布该ID的代码吗出现此错误的尝试,似乎没有提交第一个事务,因为调用方法本身是事务性的和非事务性的传播。我不知道如何进行,但现在它似乎正在工作。我将接受您的回答。(您可以在2小时内奖励您的赏金)
@Service
public class OtherBean {
@Autowired
private YourService yourService;
// note that no transactional annotation is used, this is intentional
public otherMethod() {
yourService.createImages(); // first transaction - images are committed
yourService.addImagesToArticle(); // second transaction - images are added to article
}
}