Why Hibernate does delete after update entity

Viewed 206

Im learning Hibernate and cant solve problem. Why Hibernate does delete in table "writer_post" after update entity Writer? Table writer_post have writer_id and post_id entity(Writer, Post) and have annotation @MoreToOne. What did I do wrong?

Update: I updating existing Writer. Same in table existing row for Writer.

Example:

Writer: id: 1, first_name: Dmitry, last_name: Polischuk.

Writer_post: writer_id: 1, post_id: 1.

I does update parameter only last_name.

Create tables

CREATE TABLE IF NOT EXISTS Label(
    id SERIAL PRIMARY KEY,
    name VARCHAR(50)   NOT NULL UNIQUE
);

CREATE TABLE IF NOT EXISTS Writer(
    id SERIAL PRIMARY KEY,
    first_name VARCHAR(100)  NOT NULL,
    last_name VARCHAR(100)   NOT NULL
);

CREATE TABLE IF NOT EXISTS Post(
    id SERIAL PRIMARY KEY,
    content VARCHAR(100)        NOT NULL,
    create_date TIMESTAMP DEFAULT NULL,
    updated_date TIMESTAMP DEFAULT NULL,
    status VARCHAR(30)          NOT NULL
);

CREATE TABLE IF NOT EXISTS Post_Label(
    label_id INT NOT NULL,
    post_id INT NOT NULL,
    FOREIGN KEY (post_id) REFERENCES Post(id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (label_id) REFERENCES Label(id) ON DELETE CASCADE ON UPDATE CASCADE
);

CREATE TABLE IF NOT EXISTS Writer_Post(
    post_id INT NOT NULL,
    writer_id INT NOT NULL,
    FOREIGN KEY (post_id) REFERENCES Post(id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (writer_id) REFERENCES Writer(id) ON DELETE CASCADE ON UPDATE CASCADE
); 

Entity Writer

@Getter
@Setter
@RequiredArgsConstructor
@Entity
@Table(name = "Writer")
public class Writer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    @Column(name = "first_name")
    private String firstName;
    @Column(name = "last_name")
    private String lastName;
    @ManyToOne(targetEntity = Post.class, cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinTable(name = "writer_post",
                joinColumns = @JoinColumn(name = "writer_id"),
                inverseJoinColumns = @JoinColumn(name = "post_id"))
    private List<Post> posts;

Entity Post

@Getter
@Setter
@RequiredArgsConstructor
@Entity
@Table(name = "Post")
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;
    @Column(name = "Content")
    private String content;
    @Column(name = "create_date")
    private Date created;
    @Column(name = "updated_date")
    private Date updated;
    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private PostStatus status;
    @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinTable(name = "post_label",
                joinColumns = @JoinColumn(name = "post_id"),
                inverseJoinColumns = @JoinColumn(name = "label_id"))
    private List<Label> labels;

Code for update Writer

@Override
    public Writer update(Writer writer) {
        try(Session session = HibernateUtil.getSessionFactory().openSession()){
            session.beginTransaction();
            session.saveOrUpdate(writer);
            session.getTransaction().commit();
            return writer;
        }
    }

Result stacktrace

Hibernate: update Writer set first_name=?, last_name=? where id=?
Hibernate: delete from writer_post where writer_id=?
1 Answers

Your mapping looks like one post can be mapped to many writers. I guess you meant vice-versa. So, it's worth trying to change this:

@ManyToOne(targetEntity = Post.class, cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
        @JoinTable(name = "writer_post",
                    joinColumns = @JoinColumn(name = "writer_id"),
                    inverseJoinColumns = @JoinColumn(name = "post_id"))
        private List<Post> posts;

to this:

@OneToMany(targetEntity = Post.class, cascade = CascadeType.MERGE, fetch = FetchType.LAZY)
    @JoinTable(name = "writer_post",
                joinColumns = @JoinColumn(name = "writer_id"),
                inverseJoinColumns = @JoinColumn(name = "post_id"))
    private List<Post> posts; 
Related