hibernate 刷新

Hibernate将开发人员的思维方式从思考SQL转变为思考对象状态转换。 根据Hibernate Docs,实体可能处于以下状态之一:

  • new / transient:实体不与持久性上下文相关联,因为它是数据库不知道的新创建的对象。
  • 持久性:实体与持久性上下文相关联(位于第一级缓存中),并且存在一个表示该实体的数据库行。
  • 分离:实体先前与持久性上下文相关联,但是持久性上下文已关闭,或者手动移出了实体。
  • 已删除:实体被标记为已删除,并且持久性上下文将在刷新时从数据库中将其删除。

通过调用EntityManager方法来将对象从一种状态移动到另一种状态,例如:

  • 坚持()
  • 合并()
  • 去掉()

级联允许将给定事件从父级传播到子级,也简化了实体关系管理的管理。

在刷新期间,Hibernate会将当前持久性上下文记录的更改转换为SQL查询。

现在,请考虑以下代码中发生了什么(为简洁起见,将其简化):

@Entity
public class Product {@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "product", orphanRemoval = true)@OrderBy("index")private Set images = new LinkedHashSet();public Set getImages() {return images;}public void addImage(Image image) {images.add(image);image.setProduct(this);}public void removeImage(Image image) {images.remove(image);image.setProduct(null);}
}@Entity
public class Image {@Column(unique = true)private int index;@ManyToOneprivate Product product;public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}public Product getProduct() {return product;}public void setProduct(Product product) {this.product = product;}
}final Long productId = transactionTemplate.execute(new TransactionCallback() {@Overridepublic Long doInTransaction(TransactionStatus transactionStatus) {Product product = new Product();Image frontImage = new Image();frontImage.setIndex(0);Image sideImage = new Image();sideImage.setIndex(1);product.addImage(frontImage);product.addImage(sideImage);entityManager.persist(product);return product.getId();}
});try {transactionTemplate.execute(new TransactionCallback() {@Overridepublic Void doInTransaction(TransactionStatus transactionStatus) {Product product = entityManager.find(Product.class, productId);assertEquals(2, product.getImages().size());Iterator imageIterator = product.getImages().iterator();Image frontImage = imageIterator.next();assertEquals(0, frontImage.getIndex());Image sideImage = imageIterator.next();assertEquals(1, sideImage.getIndex());Image backImage = new Image();sideImage.setName("back image");sideImage.setIndex(1);product.removeImage(sideImage);product.addImage(backImage);entityManager.flush();return null;}
});fail("Expected ConstraintViolationException");
} catch (PersistenceException expected) {assertEquals(ConstraintViolationException.class, expected.getCause().getClass());
}

由于存在Image.index唯一约束,因此在刷新期间会收到ConstraintviolationException。

您可能想知道为什么会发生这种情况,因为我们在添加具有相同索引的backImage之前调用sideImage的remove,答案是刷新操作顺序。

根据Hibernate JavaDocs ,SQL操作顺序为:

  • 插入
  • 更新
  • 集合元素的删除
  • 集合元素的插入
  • 删除

因为我们的图像集合是“ mappedBy”,所以图像将控制关联,因此“ backImage”插入发生在“ sideImage”删除之前。

select product0_.id as id1_5_0_, product0_.name as name2_5_0_ from Product product0_ where product0_.id=?
select images0_.product_id as product_4_5_1_, images0_.id as id1_1_1_, images0_.id as id1_1_0_, images0_.index as index2_1_0_, images0_.name as name3_1_0_, images0_.product_id as product_4_1_0_ from Image images0_ where images0_.product_id=? order by images0_.index
insert into Image (id, index, name, product_id) values (default, ?, ?, ?)
ERROR: integrity constraint violation: unique constraint or index violation; UK_OQBG3YIU5I1E17SL0FEAWT8PE table: IMAGE

要解决此问题,您必须在除去操作之后手动刷新持久性上下文:

transactionTemplate.execute(new TransactionCallback<Void>() {@Overridepublic Void doInTransaction(TransactionStatus transactionStatus) {Product product = entityManager.find(Product.class, productId);assertEquals(2, product.getImages().size());Iterator<Image> imageIterator = product.getImages().iterator();Image frontImage = imageIterator.next();assertEquals(0, frontImage.getIndex());Image sideImage = imageIterator.next();assertEquals(1, sideImage.getIndex());Image backImage = new Image();backImage.setIndex(1);product.removeImage(sideImage);entityManager.flush();product.addImage(backImage);entityManager.flush();return null;}
});

这将输出所需的行为:

select versions0_.image_id as image_id3_1_1_, versions0_.id as id1_8_1_, versions0_.id as id1_8_0_, versions0_.image_id as image_id3_8_0_, versions0_.type as type2_8_0_ from Version versions0_ where versions0_.image_id=? order by versions0_.type
delete from Image where id=?
insert into Image (id, index, name, product_id) values (default, ?, ?, ?)
  • 源代码在这里 。
参考: Hibernate Facts:在Vlad Mihalcea的Blog博客上 ,我们的JCG合作伙伴 Vlad Mihalcea 知道冲洗操作的顺序很重要 。

翻译自: https://www.javacodegeeks.com/2013/11/hibernate-facts-knowing-flush-operations-order-matters.html

hibernate 刷新

hibernate 刷新_Hibernate事实:了解刷新操作顺序很重要相关推荐

  1. php刷新onload(),JS页面刷新的方法总结

    我们在前面介绍了JavaScript刷新页面location.reload()的用法,其实在JS中刷新页面的方法有很多种,这只是其中的一种,那么今天我们就带大家学习下JS刷新页面的方法总结! wind ...

  2. vue使用provide / inject 组合刷新页面+单独组件刷新

    原文链接:https://www.cnblogs.com/leng12/p/xiaoleng.html 一.this.$router.go(0) 相当于F5刷新,这种方法虽然代码很少,只有一行,但是体 ...

  3. jquery刷新当前页面、刷新父级页面

    jquery刷新当前页面.刷新父级页面 window.location.reload(); // 刷新当前页面 parent.location.reload(); // 刷新父级页面 opener.l ...

  4. 服务器刷新率和显示器刷新率,显示器的刷新率是什么?

    显示器的刷新率是什么? 在早期的CRT时代,很少有玩家会去关注显示器刷新率这个参数,因为那个时代的显示器刷新率完全满足玩家们的需求,而到了液晶显示器时代早期的液晶显示器的刷新率大多在60Hz或75Hz ...

  5. 修改手机屏幕刷新率_什么是屏幕刷新率?高刷新率屏幕为手机带来什么

    [维文信TP世界]当年乔布斯说道:"当你距离屏幕10-12英寸时,300以上的ppi就分辨不出像素点."显然,现在人们已经不再满足这"10-12英寸"距离的限制 ...

  6. android游戏boss坐标,热血江湖手游boss刷新点坐标 boss刷新时间 _图文攻略_高分攻略_百度攻略...

    热血江湖手游的boss都是有固定的刷新时间和刷新坐标的,你如果不知道boss的刷新位置,好东西落入别人的口袋你就只能看看喽!下面小编给大家带来各boss刷新坐标和刷新时间. 在成功击杀BOSS后,参与 ...

  7. vue 添加完数据后刷新页面_页面刷新vuex数据消失

    1.前言 vue构建的项目中,vuex的状态存储是响应式的,当vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会得到高效刷新,问题来了,vuex存储的数据只是在页 ...

  8. 用函数刷新页面内容比刷新页面要好

    用函数刷新页面内容比刷新页面要好 app中有时需要更新页面的内容,这个时候可以选择刷新该页面 但如果使用函数来更改页面的内容,效果会更好: 例如 转载于:https://www.cnblogs.com ...

  9. Android PullToRefreshListView上拉刷新和下拉刷新

    PullToRefreshListView实现上拉和下拉刷新有两个步骤: 1.设置刷新方式 pullToRefreshView.setMode(PullToRefreshBase.Mode.BOTH) ...

最新文章

  1. 编译器中代码自动对齐快捷键
  2. 根据注释生成项目文档
  3. 源服务器未能找到目标资源的表示或者不愿,java - 源服务器没有找到目标资源的当前表示,或者不愿意透露一个存在。 关于部署到 tomcat - 堆栈内存溢出...
  4. 在向服务器发送请求时发生传输级错误。
  5. 开发 高质量 android应用 pdf,《打造高质量Android应用》读书笔记
  6. 如何申请CSDN博客?
  7. 工作缺点和不足及措施_个人工作缺点和不足
  8. 5G注册流程分级详解Step4-8
  9. 辉芒微IO单片机FT60F024-RB
  10. 卡片式超声波水表优势
  11. 常用小波基函数以及多尺度多分辨率的理解
  12. 成功解决raise AssertionError(“Torch not compiled with CUDA enabled“)AssertionError: Torch not compiled
  13. 计算机教育传播理论,-通信传播论文:计算机理论教育探讨
  14. Bursuite暴力破解实践
  15. 秋月之谋:恒生指数弱势反抽继续空,德指阴阳变幻继续空!
  16. L2TP客户端之Strongswan移植(一)
  17. Vue.js--下拉菜单组件
  18. Spark3大数据实时处理-Streaming+Structured Streaming 实战(完整版)
  19. 论文阅读笔记(1)Beyond Natural Motion: Exploring Discontinuity for Video Frame Interpolation——超越自然运动: 探索视频帧
  20. 【FPGA】定点数 数据位宽 运算 位宽截取

热门文章

  1. codeforces gym-101745 C-Infinite Graph Game 分块
  2. Spark入门(十五)之分组求最小值
  3. Oracle入门(五D)之如何设置show parameter显示隐含参数
  4. 装饰器模式(讲解+应用)
  5. Spring 知识点详解
  6. Java中的binarySearch方法
  7. ssh(Spring+Spring mvc+hibernate)——applicationContext.xml
  8. JS删除之前弹出一个带有确认和取消按钮的提示框confirm()
  9. 遍历线索化二叉树+图解
  10. xml vs db.properties