Home > database >  JPA: unidirectional many-to-one and cascading all
JPA: unidirectional many-to-one and cascading all

Time:10-03

Say I have a unidirectional @ManyToOne relationship like the following:


    @Entity
    @Table(name = "TestUser")
    @AllArgsConstructor
    @NoArgsConstructor
    @Getter
    @Setter
    public class TestUser {
    
        @Id
        @Column(nullable = false)
        private String id;
    
        @Column(name = "some_property")
        private String someProperty;
    
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof TestUser)) return false;
            return id != null && id.equals(((TestUser) o).getId());
        }
    
        @Override
        public int hashCode() {
            return getClass().hashCode();
        }
    }
    
    @Entity
    @Setter
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public class BugTicket {
    
        @Id
        @GeneratedValue
        @Column(name = "id", nullable = false)
        private Long id;
    
        @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
        @JoinColumn
        private TestUser testUser;
    
        public BugTicket(TestUser testUser) {
            this.testUser = testUser;
        }
    }
    
    class Driver {
    
        public void run(String... args) throws Exception {
            TestUser u1 = new TestUser("user-id-1", "value1");
            userRepository.save(u1);
    
            var ticket = new BugTicket(u1);
            ticketRepository.save(ticket);
    
            ticket.getTestUser().setSomeProperty("value2");
            ticketRepository.save(ticket);
        }
    }

I want to update the user entity's 'someProperty' whenever I update BugTicket entity. Hence I added CascadeType.ALL to BugTicket's user.

However, when save is called, hibernate tries to create a new user and throws exception


    Hibernate: insert into test_user (some_property, id) values (?, ?)
    2022-10-02 18:33:39.404  WARN 30632 --- [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 23505
    2022-10-02 18:33:39.405 ERROR 30632 --- [  restartedMain] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: duplicate key value violates unique constraint "test_user_pkey"
      Detail: Key (id)=(user-id-1) already exists.

Why does hibernate try to insert User once again? Is removing CascadeType.all from BugTicket, and explicitely saving user ' ticket.getTestUser().setSomeProperty("value2");' the only way?

CodePudding user response:

When you save an entity with jparepository it returns the persisted user so you need to use that

CodePudding user response:

When you try to save your "ticket", ticket.getTestUser() is detached so Hibernate will try to create it. You need to work inside a transaction.

  • Related