使用uniq字段保存数据

时间:2017-07-07 07:49:26

标签: hibernate

问题:对于简单示例,我们有下表:

 @Entity
 @Table(name = "books")
 public class Book {
     // other columns
     private Set<Genre> genres = new LinkedHashSet<>();

     @ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
     @JoinTable(name = "book_genre", joinColumns = {@JoinColumn(name="book_id")}, inverseJoinColumns = {@JoinColumn(name="genre_id")})
     @OrderBy("name ASC")    
     public Set<Genre> getGenres() {
             return genres;
     }
 }

类型表格(实体)具有唯一列名称,此列已包含名称为示例类型的行,现在如果我&#39 ; ll尝试保存具有相同类型名称的新图书实体:

  Set<Genre> newBookGenres = new LinkedHashSet<>();
  Genre newBookGenre = new Genre("Example genre"); //new genre with name [Example genre]
  newBookGenres.add(newBookGenre);
  Book book = new Book(newBookGenres);
  session.save(book);

它不会保存该书并为唯一列抛出异常(示例类型已存在于流派名称中)。

问题:我该如何保存这样的实体?我想,在保存这本书之前,我可以在流派表中搜索该书的类型名称,如果有(在数据库中)具有相同名称的流派,则只需将书籍类型对象替换为数据库流派对象。但我不确定它是否会起作用,并相信有更简单的方法。

1 个答案:

答案 0 :(得分:2)

你是变体,是好的,有效的变体。这是一个很好的实践。你可以在java方面添加一些验证,以验证该对象已经存在,而不是在验证失败时调用dao方法进行保存。在这种情况下,您不需要尝试保存实体并捕获异常。您可以通过验证节省时间,因为save()方法可能不像您展示的那么简单。

此外,您可以将dao方法包装为save()它捕获块并使用异常,但这是不好的做法,因为您应该使用运行时异常,而不是事先通过验证来处理它。

由于您的实体(副本)可能在保存期间被其他用户或用户修改,因此即使您的验证正常,也可能会导致db constains问题。在这种情况下,使用版本进行乐观锁定。

另外,如果可以,请提前进行所有检查。