java - @OneToMany 和 @ManyToOne 双向链接时关联实体的保存不正确
问题描述
我不明白为什么这么多额外的记录会保存到父表中。可能是什么问题?
- 实体
@Entity
@Table(name ="posts")
public class Post {
@Id
@SequenceGenerator(name = "jpaSequence.Post",
sequenceName = "SEQUENCE_POST",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.Post")
private Long id;
private String subject;
@OneToMany(mappedBy = "post", cascade = {CascadeType.ALL})
private List<Comment> comments = new ArrayList<>();
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User user;
public Post() {
}
@Entity
@Table(name = "comments")
public class Comment {
@Id
@SequenceGenerator(name = "jpaSequence.Comment",
sequenceName = "SEQUENCE_COMMENT",
allocationSize = 1, initialValue = 4)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.Comment")
private Long id;
private String reply;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn
private Post post;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User user;
public Comment() {
}
@Entity
@Table(name = "users")
public class User {
@Id
@SequenceGenerator(name = "jpaSequence.User",
sequenceName = "SEQUENCE_USER",
allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.User")
private Long id;
private String name;
private String email;
public User() {
}
json
{
"id": null,
"subject": "JPA Entity Graph - saved new",
"comments": [
{
"id": null,
"reply": "new techology !!",
"post": {
"id": null
},
"user": {
"id": 2,
"name": "user2",
"email": "user2@test.com"
}
},
{
"id": null,
"reply": "new techology and good tecnology !!",
"post": {
"id": null
},
"user": {
"id": 3,
"name": "user3",
"email": "user3@test.com"
}
}
],
"user": {
"id": 1,
"name": "user1",
"email": "user1@test.com"
}
}
也许在儿童记录方面,我该如何限制这种循环?
更新 1
- 服务
@Service
public class PostSaveServiceImpl implements PostSaveService{
private PostRepository repository;
private PostWithoutNestedLevelsTransformers transformer;
@Autowired
public PostSaveServiceImpl(PostRepository repository,
PostWithoutNestedLevelsTransformers transformer) {
this.repository = repository;
this.transformer = transformer;
}
@Transactional
@Override
public PostDto setData(PostDto dto) {
Post post = this.transformer.transformDtoToEntity(dto);
Post postSaved = saveData(post);
PostDto postDto = this.transformer.transformEntityToDto(postSaved);
return postDto;
}
private Post saveData(Post post){
Post save = this.repository.save(post);
return save;
}
@Transactional
@Override
public Iterable<PostDto> setListData(Iterable<PostDto> listDto) {
return null;
}
}
- 存储库
public interface PostRepository extends CrudRepository<Post, Long> {
@EntityGraph(attributePaths = {
"comments",
"user"
})
Optional<Post> findById(Long id);
}
如果我删除{CascadeType.ALL}在实体子的一边,我得到
{
"id": 71,
"subject": "JPA Entity Graph - saved new",
"comments": [
{
"id": null,
"reply": "new techology !!",
"post": null,
"user": {
"id": 2,
"name": "user2",
"email": "user2@test.com"
}
},
{
"id": null,
"reply": "new techology and good tecnology !!",
"post": null,
"user": {
"id": 3,
"name": "user3",
"email": "user3@test.com"
}
}
],
"user": {
"id": 1,
"name": "user1",
"email": "user1@test.com"
}
}
评论不会写。
如果我放的话,在实体孩子的一边
@ManyToOne(fetch = FetchType.LAZY, cascade = {
CascadeType.MERGE,
CascadeType.PERSIST
})
,我明白了
14-04-2020 11:25:13.740 DEBUG 27144 org.hibernate.SQL :
select
sequence_post.nextval
from
dual
14-04-2020 11:25:13.746 DEBUG 27144 o.h.id.enhanced.SequenceStructure : Sequence value obtained: 75
14-04-2020 11:25:13.746 DEBUG 27144 o.h.r.j.i.ResourceRegistryStandardImpl : HHH000387: ResultSet's statement was not registered
14-04-2020 11:25:13.747 DEBUG 27144 o.h.e.i.AbstractSaveEventListener : Generated identifier: 75, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
14-04-2020 11:25:13.760 DEBUG 27144 org.hibernate.SQL :
select
sequence_comment.nextval
from
dual
14-04-2020 11:25:13.822 DEBUG 27144 o.h.id.enhanced.SequenceStructure : Sequence value obtained: 42
14-04-2020 11:25:13.822 DEBUG 27144 o.h.r.j.i.ResourceRegistryStandardImpl : HHH000387: ResultSet's statement was not registered
14-04-2020 11:25:13.822 DEBUG 27144 o.h.e.i.AbstractSaveEventListener : Generated identifier: 42, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
14-04-2020 11:25:13.822 DEBUG 27144 org.hibernate.SQL :
select
sequence_post.nextval
from
dual
14-04-2020 11:25:13.823 DEBUG 27144 o.h.id.enhanced.SequenceStructure : Sequence value obtained: 76
14-04-2020 11:25:13.823 DEBUG 27144 o.h.r.j.i.ResourceRegistryStandardImpl : HHH000387: ResultSet's statement was not registered
14-04-2020 11:25:13.823 DEBUG 27144 o.h.e.i.AbstractSaveEventListener : Generated identifier: 76, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
14-04-2020 11:25:13.824 DEBUG 27144 org.hibernate.SQL :
select
sequence_comment.nextval
from
dual
14-04-2020 11:25:13.826 DEBUG 27144 o.h.id.enhanced.SequenceStructure : Sequence value obtained: 43
14-04-2020 11:25:13.827 DEBUG 27144 o.h.r.j.i.ResourceRegistryStandardImpl : HHH000387: ResultSet's statement was not registered
14-04-2020 11:25:13.827 DEBUG 27144 o.h.e.i.AbstractSaveEventListener : Generated identifier: 43, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
14-04-2020 11:25:13.827 DEBUG 27144 org.hibernate.SQL :
select
sequence_post.nextval
from
dual
14-04-2020 11:25:13.828 DEBUG 27144 o.h.id.enhanced.SequenceStructure : Sequence value obtained: 77
14-04-2020 11:25:13.828 DEBUG 27144 o.h.r.j.i.ResourceRegistryStandardImpl : HHH000387: ResultSet's statement was not registered
14-04-2020 11:25:13.828 DEBUG 27144 o.h.e.i.AbstractSaveEventListener : Generated identifier: 77, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
14-04-2020 11:25:13.828 TRACE 27144 o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
14-04-2020 11:25:13.828 TRACE 27144 o.s.t.i.TransactionInterceptor : Completing transaction for [com.web.service.save.post.impl.PostSaveServiceImpl.setData]
14-04-2020 11:25:13.829 DEBUG 27144 o.h.e.t.internal.TransactionImpl : committing
14-04-2020 11:25:13.829 DEBUG 27144 o.h.e.i.AbstractFlushingEventListener : Processing flush-time cascades
14-04-2020 11:25:13.830 DEBUG 27144 o.h.e.i.AbstractFlushingEventListener : Dirty checking collections
14-04-2020 11:25:13.833 DEBUG 27144 o.hibernate.engine.internal.Collections : Collection found: [com.dao.domain.post.Post.comments#75], was: [<unreferenced>] (initialized)
14-04-2020 11:25:13.833 DEBUG 27144 o.hibernate.engine.internal.Collections : Collection found: [com.dao.domain.post.Post.comments#76], was: [<unreferenced>] (initialized)
14-04-2020 11:25:13.833 DEBUG 27144 o.hibernate.engine.internal.Collections : Collection found: [com.dao.domain.post.Post.comments#77], was: [<unreferenced>] (initialized)
14-04-2020 11:25:13.834 DEBUG 27144 o.h.e.i.AbstractFlushingEventListener : Flushed: 5 insertions, 0 updates, 0 deletions to 5 objects
14-04-2020 11:25:13.834 DEBUG 27144 o.h.e.i.AbstractFlushingEventListener : Flushed: 3 (re)creations, 0 updates, 0 removals to 3 collections
14-04-2020 11:25:13.834 DEBUG 27144 o.hibernate.internal.util.EntityPrinter : Listing entities:
14-04-2020 11:25:13.834 DEBUG 27144 o.hibernate.internal.util.EntityPrinter : com.dao.domain.post.Post{comments=[], subject=null, id=76, user=null}
14-04-2020 11:25:13.834 DEBUG 27144 o.hibernate.internal.util.EntityPrinter : com.dao.domain.post.Post{comments=[], subject=null, id=77, user=null}
14-04-2020 11:25:13.834 DEBUG 27144 o.hibernate.internal.util.EntityPrinter : com.dao.domain.comment.Comment{post=com.dao.domain.post.Post#77, id=43, reply=new techology and good tecnology !!, user=com.dao.domain.users.User#3}
14-04-2020 11:25:13.834 DEBUG 27144 o.hibernate.internal.util.EntityPrinter : com.dao.domain.post.Post{comments=[com.dao.domain.comment.Comment#42, com.dao.domain.comment.Comment#43], subject=JPA Entity Graph - saved new, id=75, user=com.dao.domain.users.User#1}
14-04-2020 11:25:13.835 DEBUG 27144 o.hibernate.internal.util.EntityPrinter : com.dao.domain.comment.Comment{post=com.dao.domain.post.Post#76, id=42, reply=new techology !!, user=com.dao.domain.users.User#2}
14-04-2020 11:25:13.839 DEBUG 27144 org.hibernate.SQL :
insert
into
posts
(subject, user_id, id)
values
(?, ?, ?)
14-04-2020 11:25:13.839 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [JPA Entity Graph - saved new]
14-04-2020 11:25:13.840 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
14-04-2020 11:25:13.840 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [75]
14-04-2020 11:25:13.842 DEBUG 27144 org.hibernate.SQL :
insert
into
posts
(subject, user_id, id)
values
(?, ?, ?)
14-04-2020 11:25:13.842 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [null]
14-04-2020 11:25:13.842 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [null]
14-04-2020 11:25:13.842 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [76]
14-04-2020 11:25:13.844 DEBUG 27144 org.hibernate.SQL :
insert
into
comments
(post_id, reply, user_id, id)
values
(?, ?, ?, ?)
14-04-2020 11:25:13.844 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [76]
14-04-2020 11:25:13.844 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [new techology !!]
14-04-2020 11:25:13.844 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [2]
14-04-2020 11:25:13.844 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [BIGINT] - [42]
14-04-2020 11:25:13.845 DEBUG 27144 org.hibernate.SQL :
insert
into
posts
(subject, user_id, id)
values
(?, ?, ?)
14-04-2020 11:25:13.845 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [null]
14-04-2020 11:25:13.845 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [null]
14-04-2020 11:25:13.845 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [77]
14-04-2020 11:25:13.847 DEBUG 27144 org.hibernate.SQL :
insert
into
comments
(post_id, reply, user_id, id)
values
(?, ?, ?, ?)
14-04-2020 11:25:13.847 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [77]
14-04-2020 11:25:13.847 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [new techology and good tecnology !!]
14-04-2020 11:25:13.847 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [3]
14-04-2020 11:25:13.847 TRACE 27144 o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [BIGINT] - [43]
14-04-2020 11:25:13.857 DEBUG 27144 o.s.w.s.m.m.a.HttpEntityMethodProcessor : Using 'application/json', given [*/*] and supported [application/json]
14-04-2020 11:25:13.866 DEBUG 27144 o.s.w.s.m.m.a.HttpEntityMethodProcessor : Writing [PostDto{id=75, subject='JPA Entity Graph - saved new', comments=[CommentDto{id=42, reply='new techol (truncated)...]
14-04-2020 11:25:13.878 DEBUG 27144 o.s.web.servlet.DispatcherServlet : Completed 200 OK
但是我在父表中获得了带有空字段的额外条目。谁知道这里有什么问题?
解决方案
在评论表上,为什么需要 cascadeType 为 ALL
CascadeType 意味着 - Comment 上发生的任何更改也必须级联到 Post。
尝试删除它
@Entity
@Table(name = "comments")
public class Comment {
@Id
@SequenceGenerator(name = "jpaSequence.Comment",
sequenceName = "SEQUENCE_COMMENT",
allocationSize = 1, initialValue = 4)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "jpaSequence.Comment")
private Long id;
private String reply;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private Post post;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn
private User user;
public Comment() {
}
推荐阅读
- python - 运行 python pptx 代码后图像损坏
- phpmyadmin - phpmyadmin 左侧面板上不显示一张表
- android - 使用可缩放的选定卡片水平刷卡
- java - 在 geeksforgeeks 上解决矩阵问题中的路径有什么问题?
- assembly - 代码段和数据段背后的基本原理
- opencv - 如何在 docker (debian:jessie) 上为 python3.5 安装 openCV
- c++ - 在 C++ 中具有模板初始化的静态结构指针
- assembly - (汇编x86实模式)数据在程序结束时被“切断”?
- c - 使用字符串方法在 C 中的 fizzbuzz 中出现错误?
- c - 虽然 C Arduino 不能循环(With 语句),但使用 MQTT