![](/img/trans.png)
[英]Spring Boot findById is not working but findAllById works fine
[英]Spring Boot JPA/JDBC batching findById works but findOneByX not working
我正在使用 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 是否僅配備批處理?
請參閱如何使用 Spring Data Jpa 實現批量更新?
saveAll
PS:當您的列表很大時,請注意此解決方案的內存使用情況。
findById
和findOneByX
的行為不同?在執行與排隊實體操作重疊的 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 用於更新。
@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 表示循環更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.