我正在使用 Spring Boot JPA,我通過確保以下行在我的 application.properties 中啟用了批處理:
spring.jpa.properties.hibernate.jdbc.batch_size=1000
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true
我現在有一個回圈,我在一個物體上執行 findById,然后像這樣保存該物體:
var entity = dao.findById(id)
// Do some stuff
dao.save(entity) //This line is not really required but I am being explicit here
將上述內容放在一個回圈中,我看到 save(update) 陳述句被批處理到資料庫。我的問題是,如果我執行 findOneByX ,其中 X 是物體上的屬性,則批處理不起作用(批處理大小為 1),請求一次發送一個,即:
var entity = dao.findOneByX(x)
// Do some stuff
dao.save(entity)
為什么會這樣?當我們僅 findById 時,JPA/JDBC 是否僅配備批處理?
uj5u.com熱心網友回復:
解決方案
請參閱如何使用 Spring Data Jpa 實作批量更新?
- 獲取要更新到串列的物體串列
- 根據需要更新
- 稱呼
saveAll
PS:當您的串列很大時,請注意此解決方案的記憶體使用情況。
為什么findById和findOneByX行為不同?
正如M. Deinum所建議的,休眠將自動重繪 您的更改
在執行與排隊物體操作重疊的 JPQL/HQL 查詢之前
既然findById和findOneByX都會執行查詢,那么它們之間有什么不同呢?
首先,重繪 的原因是確保會話和資料庫處于相同狀態,因此您可以從會話快取(如果可用)和資料庫中獲得一致的結果。
呼叫時findById,hibernate 將嘗試從會話快取中獲取它,如果物體不可用,則從資料庫中獲取它。而對于findOneByX,我們總是需要從資料庫中獲取它,因為 X 不可能快取物體。
然后我們可以考慮下面的例子:
@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Student {
@Id
private Long id;
private String name;
private int age;
}
假設我們有
| ID | 姓名 | 年齡 |
|---|---|---|
| 1 | 艾米 | 10 |
@Transactional
public void findByIdAndUpdate() {
dao.save(new Student(2L, "Dennis", 14));
// no need to flush as we can get from session
for (int i = 0; i < 100; i ) {
Student dennis = dao.findById(2L).orElseThrow();
dennis.setAge(i);
dao.save(dennis);
}
}
會導致
412041 nanoseconds spent executing 2 JDBC batches;
1 用于插入 1 用于更新。
- Hibernate:如果記錄不在會話中,我確信結果可以從會話(沒有重繪 )或資料庫中獲取,所以讓我們跳過重繪 ,因為它很慢!
@Transactional
public void findOneByNameAndUpdate() {
Student amy = dao.findOneByName("Amy");
// this affect later query
amy.setName("Tammy");
dao.save(amy);
for (int i = 0; i < 100; i ) {
// do you expect getting result here?
Student tammy = dao.findOneByName("Tammy");
// Hibernate not smart enough to notice this will not affect later result.
tammy.setAge(i);
dao.save(tammy);
}
}
會導致
13964088 nanoseconds spent executing 101 JDBC batches;
1 表示第一次更新,100 表示回圈更新。
- Hibernate:嗯,我不確定存盤的更新是否會影響結果,最好重繪 更新,否則我會被開發人員指責。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/479457.html
標籤:爪哇 春天 弹簧靴 数据库 spring-jdbc
