日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

休眠事实:了解刷新操作顺序很重要

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 休眠事实:了解刷新操作顺序很重要 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

總結

以上是生活随笔為你收集整理的休眠事实:了解刷新操作顺序很重要的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。