Неправильное сохранение связанных сущностей, когда @OneToMany и @ManyToOne связаны двунаправленно - PullRequest
0 голосов
/ 14 апреля 2020

Я не могу понять, почему так много дополнительных записей сохраняются в родительской таблице. В чем может быть проблема?

  • Entites
@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"
    }
}

  • пост (таблица) enter image description here

  • комментарии (таблица)

enter image description here

может быть, на стороне записи ребенка, как я могу ограничить этот цикл?

Update-1

  • service
@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"
    }
}

Комментарии не будут писать.

enter image description here

enter image description here

На стороне ребенка, если я поставлю

   @ManyToOne(fetch = FetchType.LAZY, cascade = {
            CascadeType.MERGE,
            CascadeType.PERSIST
    })

, я получу

enter image description here

enter image description here

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

Но я получаю дополнительные записи в родительской таблице с пустым полем. У кого есть идеи, в чем здесь проблема?

1 Ответ

0 голосов
/ 14 апреля 2020

в таблице комментариев, зачем вам нужен cascadeType, поскольку ALL

CascadeType - это то, что означает, что любое изменение, произошедшее в комментарии, также должно каскадно публиковаться.

попробуйте удалить его

@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() {
    } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...