JPA:单向多对一和全部级联

erhoui1w  于 2022-11-14  发布在  其他
关注(0)|答案(2)|浏览(116)

假设我有一个单向的@ManyToOne关系,如下所示:

@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);
        }
    }

我想在更新BugTicket实体时更新用户实体的'someProperty'。因此,我将CascadeType.ALL添加到BugTicket的用户。
但是,当调用保存时,hib会尝试创建一个新用户并抛出异常

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.

为什么Hibernate会再次尝试插入用户?是从BugTicket中删除CascadeType.all,并显式保存用户的ticket。getTestUser()。setSomeProperty(“value 2”);“唯一的办法?

iyr7buue

iyr7buue1#

当你试图保存你的“ticket”时,ticket.getTestUser()被分离,因此Hibernate将尝试创建它。你需要在事务内部工作。

ktca8awb

ktca8awb2#

当您使用jparepository保存实体时,它会返回持久化的用户,因此您需要使用它。
正如@grigouille所说,该方法应该是事务性的,因为如果没有它,当您保存BugTicket时,将尝试再次保存TestUser,因为它不是托管实体。
使方法事务像这样,它将只保存TestUser一次,并且当您稍后在方法中更新它时,它将成为托管实体,您甚至不必调用另存为Hibernate。当提交事务时,污垢检查机制将把对它的任何更改写入数据库

@Transactional
    public void saveBugTicketAndTestUser() {
        TestUser u1 = new TestUser("user-id-1", "value1");
        TestUser savedUser = userRepository.save(u1);

        BugTicket ticket = new BugTicket(savedUser);
        ticketRepository.save(ticket);

        savedUser.setSomeProperty("value2");
    }

相关问题