@Modifying(clearAutomatically = true)
@Transactional
@Query(value = "UPDATE info SET status = ?1 WHERE id = ?2", nativeQuery = true)
int updateStatusById(String status, String id);
| 註解 | 作用 | 缺失後果 |
|---|---|---|
@Query(nativeQuery = true) | 聲明使用原生 SQL 而非 JPQL | 語法報錯(JPQL 不支持 UPDATE ... SET) |
@Modifying | 標識為修改操作(INSERT/UPDATE/DELETE) | 拋出 InvalidDataAccessApiUsageException:查詢方法不能修改數據 |
@Transactional | 提供事務邊界,提交變更 | 數據不落庫(自動提交關閉時)或拋事務異常 |
?1, ?2... 對應方法參數順序:status, :id 配合 @Param("status")@Query(value = "UPDATE info SET status = :status WHERE id = :id", nativeQuery = true)
int updateStatusById(@Param("status") String status, @Param("id") String id);
| 返回類型 | 含義 | 適用場景 |
|---|---|---|
int / long | 受影響行數 | 批量更新、需確認執行結果 |
void | 無返回 | 不關心行數,簡單修改 |
boolean | 是否影響≥1行 | 邏輯判斷 |
執行修改後自動清空持久化上下文(一級緩存),避免後續讀取到舊數據(髒讀)。建議始終開啟,除非極度確定後續無讀取操作。
public interface InfoRepository extends JpaRepository<Info, String> {
@Modifying(clearAutomatically = true)
@Transactional
@Query(value = "UPDATE info SET status = ?1, update_time = NOW() WHERE id = ?2", nativeQuery = true)
int updateStatusById(String status, String id);
@Modifying
@Transactional
@Query(value = "DELETE FROM info WHERE create_time < ?1", nativeQuery = true)
int deleteExpired(Date threshold);
}
UPDATE Entity e SET e.field = ?1 WHERE e.id = ?2,但不觸發實體生命週期回調、不清理緩存,原生 SQL 更直觀可控。@QueryHints 批處理或分頁循環更新。@Version 時,原生 SQL 更新不會自動遞增版本號,導致後續樂觀鎖失效——需手動 SET version = version + 1。Spring Data JPA 執行原生 SQL 更新鐵三角:@Query(nativeQuery=true) + @Modifying + @Transactional。返回 int 獲取影響行數,clearAutomatically=true 保證緩存一致性。大批量、樂觀鎖場景需額外關注性能與版本號維護。