【问题标题】:Unique constraint on combination of more than two columns对多于两列的组合的唯一约束
【发布时间】:2020-01-06 20:16:56
【问题描述】:

我有两个表bookpage 我正在尝试在它们之间建立一个双向的一对多关系。

页面 对无法正常工作的多个列有唯一约束。当我插入具有唯一 page_item 的 book_item 时,它按预期工作,但是当我尝试删除也应该删除页面的书时,我得到 唯一约束违反异常,我真的不明白。 我正在使用 jpa 存储库来执行插入/删除。

当我删除 @UniqueConstraint 时,删除有效,但约束也无效,所以我真的不明白我做错了什么。

@Entity
@Table(name = "book")
@NoArgsConstructor
@RequiredArgsConstructor
public class Book implements Serializable {

    @Id
    @GeneratedValue(generator = "book_uuid")
    @GenericGenerator(name = "book_uuid", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(name = "id", updatable = false, nullable = false, columnDefinition = "VARCHAR(255)")
    @Type(type="uuid-char")
    @Getter
    private UUID id;


    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
    @Getter
    @Setter
    private List<Page> pages;
}


@Entity
@Table(name = "page", uniqueConstraints = @UniqueConstraint(columnNames = {"book_id", "chapter", "volume", "name"}))
@NoArgsConstructor
@RequiredArgsConstructor
public class Page implements Serializable {

    @Id
    @GeneratedValue(generator = "page_uuid")
    @GenericGenerator(name = "page_uuid", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(name = "id", updatable = false, nullable = false, columnDefinition = "VARCHAR(255)")
    @Type(type="uuid-char")
    @Getter
    private UUID id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "book_id", nullable = false)
    @Getter
    @Setter
    @NonNull
    private Book book;

    @Column(name = "chapter", nullable = false)
    @Getter
    @Setter
    private int chapter = 0;

    @Column(name = "volume", nullable = false)
    @Getter
    @Setter
    private int volume = 0;

    @Column(name = "name", nullable = false)
    @Getter
    @Setter
    @NonNull
    private String name;
}

// Code used for insertion/update /deletion


@Repository
public interface BookRepository extends JpaRepository<Book, UUID> {

}


public void test() {
    Book book = bookRepository.findById("9c7b2ab2-1c78-4e9f-adc5-99c7da42a7c6");

    List<Page> pages = IntStream.range(0, 5)
            .mapToObj(i -> new Page(book, "Page" + i, ".png"))
            .collect(Collectors.toList());
    book.setPages(pages);
    bookRepository.save(book);
    bookRepository.delete(book);

我得到的错误信息:

org.springframework.dao.DataIntegrityViolationException:无法执行语句; SQL [不适用];约束 ["UKOBQWYIY89PIIE6GP2NB4PVQ8W_INDEX_2 ON PUBLIC.PAGE(BOOK_ID, CHAPTER, VOLUME, NAME) VALUES ('acb0bb92-be2f-4dd3-9653-98f8d890e6b4', 0, 0, 'Page0', 1)"; SQL语句:

插入页面(book_id、章节、扩展名、名称、卷、id)值(?,??,?,?,?,?)[23505-197]];嵌套异常是 org.hibernate.exception.ConstraintViolationException: could not execute statement

【问题讨论】:

  • 我不会依赖级联,因为它会执行许多 SQL 查询,并删除您可能不希望删除的可能与其他实体相关的实体。而是通过执行您自己的 DELETE 语句或手动删除来管理它。有关更多信息,请参阅thoughts-on-java.org/avoid-cascadetype-delete-many-assocations。请发布您添加/删除书籍的代码。
  • 我添加了一个简单的代码 sn-p 进行插入和删除,当我执行这个时,我得到了帖子中提到的错误。
  • 首先,将@Transactional 放入您的存储库中,然后将方法deleteById 映射为javaNoob 的建议,然后让级联孤儿删除就可以了

标签: java hibernate spring-boot


【解决方案1】:

你可以试试deleteById

  deleteById("9c7b2ab2-1c78-4e9f-adc5-99c7da42a7c6");

【讨论】:

  • 错误信息表明 INSERT 有问题,而不是 DELETE
  • 可以试试@JoinColumn(name = "book_id", nullable = false,insertable = true)
  • 它与 deleteById 一起使用,但正如其他人建议的那样,我必须在我的方法中添加 @Transnational 才能使其与 delete(book) 一起使用
猜你喜欢
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 2017-04-23
  • 2010-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多