![](/img/trans.png)
[英]Hibernate fails to load JPA 2.1 Converter when loaded with spring-boot and spring-data-jpa
[英]No error when violating constraints after inserting data in spring-boot application with spring data jpa
我目前正在學習 Spring-Boot 和 Spring-Data-JPA。 我正在使用 postgresql 數據庫來存儲數據。 我的目標是存儲具有唯一和自定義 ID 的成分(您只需在創建它時輸入它),但是當插入另一個具有相同 ID 的成分時,應該會出現某種錯誤。 據我了解,當我使用 @Id 注釋時會發生這種情況,hibernate 也會記錄正確的創建表語句。 這是我的成分 class:
public class Ingredient {
@Id
@Column(name = "ingredient_id")
private String ingredient_id;
@Column(name = "name")
private String name;
@Column(name = "curr_stock")
private double curr_stock;
@Column(name = "opt_stock")
private double opt_stock;
@Column(name = "unit")
private String unit;
@Column(name = "price_per_unit")
private double price_per_unit;
@Column(name = "supplier")
private String supplier;
-- ... getters, setters, constructors (they work fine, I can insert and get the data)
}
我的 controller 看起來像這樣:
@RestController
@RequestMapping(path = "api/v1/ingredient")
public class IngredientController {
private final IngredientService ingredientService;
@Autowired
public IngredientController(IngredientService ingredientService) {
this.ingredientService = ingredientService;
}
@GetMapping
public List<Ingredient> getIngredients(){
return ingredientService.getIngredients();
}
@PostMapping
public void registerNewStudent(@RequestBody Ingredient ingredient) {
ingredientService.saveIngredient(ingredient);
}
}
而我的服務 class 只是使用 JpaRepository 中的 save() 方法來存儲新成分。
到目前為止,我有一種感覺,我理解了整個事情,但是當向我的應用程序發送兩個后請求時,每個請求都包含一個 id 為“1234”的成分,然后用一個 get 請求顯示所有成分,第一個成分剛剛被第二種替換,沒有錯誤或smth。 就像介於兩者之間。 將具有相同值的直接 sql 插入語句發送到數據庫會引發錯誤,因為違反了主鍵約束,這是應該的。 確切地說,這應該發生在第二次發布請求之后(在我的理解中)。 我做錯了什么?
更新:從終端 output 和我在下面得到的答案,現在很清楚,save() 方法可以理解為“如果主鍵已經存在則插入或更新”。 但是,有沒有比每次手動保存新條目時都錯誤處理更好的方法呢?
如果 id 已經存在,save 方法將創建或更新條目。 我會在插入時切換到自動生成 ID,而不是手動創建 ID。 這將防止您遇到的問題
保存新成分時,如果“id”字段中包含的值已在表中,jpa 將執行更新。
一個很好的方法可以實現你想要的
ingredientRepository.findById(ingredientDTO.getIngredientId()).
ifPresentOrElse( ingredientEntity-> ResponseEntity.badRequest().build(), () -> ingredientRepository.save(ingredientDTO));
如果實體已經在表中,則可以返回錯誤,否則(空 lambda),您可以保存新行
這是在應用程序設置 id 的實體上使用 CrudRepository save() 的缺點。
只有當 id 為 null 時才會調用 EntityManager.persist() ,否則會調用 EntityManager.merge() 。
直接使用 EntityManager 可以為您提供更細粒度的控制,並且您可以在需要時在應用程序中調用 persist 方法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.