spring-data-jpa 使用spring data jpa在spring-boot应用程序中插入数据后违反约束时不会出现错误

hfyxw5xn  于 2022-11-10  发布在  Spring
关注(0)|答案(3)|浏览(137)

我目前正在学习Spring-Boot和Spring-Data-JPA。我使用postgresql数据库来存储数据。我的目标是用一个唯一的自定义ID来存储成分(您只需在创建时键入它),但是当插入另一个具有相同ID的成分时,应该会出现某种错误。在我的理解中,这就是我使用@Id注解时所发生的情况,Hibernate也会记录正确的create table语句。这是我的Ingredient类:

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)
}

我的控制器如下所示:

@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);
    }

}

而我的服务类只是使用JpaRepository中的保存()方法来存储新的成分。
到目前为止,我感觉我已经理解了整个过程,但是当向我的应用程序发送两个post请求时,每个请求都包含一个id为“1234”的成分,然后用get请求显示所有成分,第一种成分刚刚被第二种成分取代,中间没有错误或类似的错误。将带有相同值的直接sql插入语句发送到数据库会引发错误,因为违反了主键约束,这是应该发生的。在我的理解中,这应该发生在第二次post请求之后。我错在哪里?
更新:从终端输出和下面得到的答案,现在很清楚,保存()方法可以理解为“如果主键已经存在,则插入或更新”。但是,在手动保存新条目时,有没有比每次都进行错误处理更好的方法呢?

a7qyws3x

a7qyws3x1#

如果id已经存在,保存方法将创建或更新条目。我会在插入时切换到自动生成ID,而不是手动创建id。这将防止您遇到的问题

mwyxok5s

mwyxok5s2#

当保存一个新成分时,如果“id”字段中包含的值已经在表中,jpa将执行更新。
一个很好的方法就是

ingredientRepository.findById(ingredientDTO.getIngredientId()).
                ifPresentOrElse( ingredientEntity-> ResponseEntity.badRequest().build(), () -> ingredientRepository.save(ingredientDTO));

如果实体已在表中,则可以返回错误,否则(空lambda),可以保存新行

8tntrjer

8tntrjer3#

这是在由应用程序设置id的实体上使用CrudRepository保存()的一个缺点。
实际上,只有当id为null时,才会调用EntityManager.persist(),否则会调用EntityManager.merge()。
直接使用EntityManager可以提供更细粒度的控制,并且可以在需要时在应用程序中调用persist方法

相关问题