【发布时间】:2019-03-08 07:10:04
【问题描述】:
我有两个以多对多关系连接的类:
Book.java
@Entity
@Table(name = "book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "book_id")
private Long id;
@Column(nullable = false)
private String title;
private String description;
@Column(name = "release_date")
@Temporal(TemporalType.TIMESTAMP)
private Date releaseDate;
@JoinColumn(name = "cover_image")
@OneToOne(cascade = CascadeType.MERGE)
private UploadFile coverImage;
@OneToOne(cascade = CascadeType.MERGE)
private UploadFile content;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "book_category", joinColumns = {@JoinColumn(name = "book_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "category_id", referencedColumnName = "id")})
private Set<Category> categories;
}
Category.java
@Entity
@Table(name = "category")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "category_id")
private Long id;
@Column(name = "category_name")
private String name;
@ManyToMany(mappedBy = "categories", fetch = FetchType.LAZY) // I also tried an option with adding cascade = CascadeType.ALL
private List<Book> books;
}
当我想将书籍添加到数据库时,我收到以下异常:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.github.model.Category; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.github.model.Category
有趣的是,从 Category 类中删除 @GeneratedValue 注释会使一切都尽可能正常工作。要添加书籍,我扩展了 JpaRepository:
public interface Repository extends JpaRepository<Book, Long>{
}
然后
Repository repository;
repository.save(book);
我在使用 h2 数据库时也应该很重要。查看所有代码可以访问我的github:https://github.com/mmaciula/Library/tree/master/src/main/java/com/github
编辑
在我添加了@Column 注释后,InvalidDataAccessApiUsageException 的问题就解决了。但是,映射集合的问题出现了。这是我收到的堆栈跟踪:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unable to map collection com.github.model.Book.categories
Caused by: org.hibernate.AnnotationException: Unable to map collection com.github.model.Book.categories
Caused by: org.hibernate.cfg.RecoverableException: Unable to find column with logical name: id in org.hibernate.mapping.Table(book) and its related supertables and secondary tables
Caused by: org.hibernate.MappingException: Unable to find column with logical name: id in org.hibernate.mapping.Table(book) and its related supertables and secondary tables
编辑 2
当我将 @JoinTable 中的 referencedColumnName 从 id 更改为 book_id 时,我收到了如下所示的 DataIntegrityViolationException:
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FKAM8LLDERP40MVBBWCEQPU6L2S: PUBLIC.BOOK_CATEGORY FOREIGN KEY(CATEGORY_ID) REFERENCES PUBLIC.CATEGORY(CATEGORY_ID) (1)"; SQL statement:
insert into book_category (book_id, category_id) values (?, ?) [23506-196]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
【问题讨论】:
-
似乎您只需要添加 CascadeType.ALL 作为该关系的级联类型。这应该使它工作 @ManyToMany(mappedBy = "categories", fetch = FetchType.LAZY, cascadeType=CascadeType.ALL)
-
@GSUgambit 我尝试添加
CascadeType.ALL,但仍然出现异常。 -
也许您应该将级联类型添加到类别侧。您的问题的根源是该类别没有持久化,因此它无法将书保存到“分离”[未保存/由休眠管理]类别。通常 casecade 类型可以解决这个问题。抱歉,我有点困,但也许将其添加到其他课程会对您有所帮助。否则,您应该在尝试保留该书之前保留该类别,尽管我认为您不必这样做。
-
在将级联类型添加到类别端后,我遇到了另一个异常:
org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["FKAM8LLDERP40MVBBWCEQPU6L2S: PUBLIC.BOOK_CATEGORY FOREIGN KEY(CATEGORY_ID) REFERENCES PUBLIC.CATEGORY(ID) (2)"; SQL statement: insert into book_category (book_id, category_id) values (?, ?) [23506-196]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement -
我看到您在表中引用了列,但发布的代码没有 ID 所需的注释。将 AT 更改为注释(它认为我试图标记人) 在书中你应该 ATColumn(name = "book_id") ATId ATGeneratedValue(strategy = GenerationType.IDENTITY) private Long id;并在类别 ATColumn(name = "category_id") ATId ATGeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
标签: java spring-boot jpa