簡體   English   中英

在使用 spring 數據 jpa 的 spring-boot 應用程序中插入數據后違反約束時沒有錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM