在 H2 中保留多对多实体会引发异常



>我有 2 个实体,两者都有彼此的列表。

类"帖子":

@ManyToMany(mappedBy = "posts", cascade=CascadeType.ALL)
private List<Tag> tags;

类"标签":

@ManyToMany(cascade = CascadeType.ALL)
@JoinTable
private List<Post> posts;`

在数据库中,我有"POSTS"表,"TAGS"表和"TAGS_POSTS"用于多对多关系。数据库中的结构和数据库中的表都很好。但是当我开始坚持帖子表中的帖子时,发生了错误。

这是用于将新帖子添加到数据库的代码,相同的代码适用于其他实体,即使对于也具有多对多关系的"标签"。

private EntityManagerFactory emf;
@PersistenceUnit
public void setEmf(EntityManagerFactory emf) {
this.emf = emf;
}
public Post add(Post post) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(post);
em.getTransaction().commit();
return post;
}

现在在应用程序开始时,我尝试用一些虚拟数据填充数据库以进行测试。具有相同代码的所有其他实体都工作正常,除了 Post。

这是代码(我尝试不设置标签属性,将其设置为空 ArrayList,并将其设置为数据库结果中已经存在的标签列表是相同的):

ApplicationContext ac =  SpringApplication.run(PostsPortalApplication.class, args);

PostsService ps = (PostsService) ac.getBean("postsService");
Post post = new Post();
post.setId(j);
post.setDate(new Date());
post.setDescription("desc" +  "/" );
post.setDislikes(5);
post.setLikes(5);
post.setLocationLat(5);
post.setLocationLong(5);
post.setPhotoUrl("URL" +  "/" + j);
post.setTitle("Title"  + "/" + j);
post.setUser(user);
post.setTags(new ArrayList<>());
ps.add(post);

这是异常消息(PostsService.java:38是行):em.persist(post);

线程"main"中的异常 javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: 传递给 persist: jovan.sf_62_2017.postsportal.pojo.Post at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157) at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:164) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:789) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:767) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:350) at com.sun.proxy.$Proxy 85.persist(未知来源) at jovan.sf_62_2017.postsportal.services.implementations.PostsService.add(PostsService.java:38) 在jovan.sf_62_2017.postsportal。PostsPortalApplication.main(PostsPortalApplication.java:67)

由以下原因引起:org.hibernate.PersistentObjectException:传递给 persist: jovan.sf_62_2017.postsportal.pojo.Post at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:782) ...9 更多

首先请更改:

cascade=CascadeType.ALL

自:

cascade = {CascadeType.PERSIST, CascadeType.MERGE}

因为使用 CascadeType.ALL 时会自动继承 CascadeType.REMOVE ,但实体删除不仅应用于链接表,还应用于关联的另一端。(见听)

所以试试这段代码:

@ManyToMany(mappedBy = "posts", 
cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private List<Tag> tags;


@ManyToMany(cascade = 
{CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(name = "post_tag",
joinColumns = {
@JoinColumn(
name = "tag_id", 
referencedColumnName = "id"
)
},
inverseJoinColumns = {
@JoinColumn(
name = "post_id", 
referencedColumnName = "id"
)
}
)
private List<Post> posts;

但是你的问题....您尝试使用持久化方法将分离的对象((意味着该对象的实例已保存到数据库中,但该对象不在会话中))保存到数据库:

Post post = new Post();
post.setId(j);
.
.
.
em.persist(post)

persist 方法旨在将新实体(没有 id 设置)实例添加到持久性上下文中,即将实例从瞬态转换为持久状态。

我们通常在要向数据库插入记录(持久化实体实例)时调用它 所以 如果对象具有暂时性或持久状态,则可以使用 persist 方法,但如果对象在分离之前应使用 merge 方法保存它

取而代之的是:

@ManyToMany(cascade = CascadeType.ALL) @JoinTable 私人列表<帖子>帖子;

请尝试以下操作:

private List<Post> posts = new ArrayList<>();
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(
name = "posts_tags",
joinColumns = { @JoinColumn(name = "fk_tags") },
inverseJoinColumns = { @JoinColumn(name = "fk_posts") }
)
public List<Post> getPosts() {
return posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}

在这里,hibernate将为多对多关系映射创建一个名为(posts_tags)的中间表。

现在让我们简化 DAO 服务:

@PersistenceContext(unitName = "myPersistenceUnit")
private EntityManager em;
@Transactional(value = "myTransactionManager",propagation = Propagation.REQUIRED)
public Post add(Post post) {
em.persist(post);
return post;
}

最新更新