首页 > 解决方案 > 我如何要求对@PrimaryKeyJoinColumn 强制执行?

问题描述

我正在创建一个 SpringBoot 应用程序,它的部分功能是创建用户,以及这些用户之间的对话。创建了以下实体..

  1. 用户(参与对话的人)
  2. 对话(记录持有对话的拥有用户)
  3. ConversationUser(记录持有所涉及的用户以及进行哪个对话)

问题是,我的 JpaRepository.save(ConversationUser) 让我插入一条带有不存在用户引用的记录。如何强制此 ConversationUser 仅在关联用户具有现有 ID 时才能插入?

我尝试在 ConversationUser 上使用@ManyToOneand@PrimaryKeyJoinColumn来尝试强制执行真实记录的存在,但没有成功。

User.class

@Entity
public class User {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(updatable = false, unique = true, nullable = false)
    @Type(type = "uuid-char")
    protected UUID id;

    @Column(unique = true, nullable = false)
    protected String username;

    @Column(nullable = false)
    protected char[] password;

    @Column(nullable = false)
    protected String firstName, lastName;

    @Column(unique = true, nullable = false)
    protected String email;
}

ConversationUser.class

@Entity
@Table(uniqueConstraints = {
        @UniqueConstraint(columnNames = {
                "conversation_id",
                "user_id"
        })
})
public class ConversationUser {

    @Id
    @GeneratedValue(generator = "uuid2")
    @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator")
    @Column(updatable = false, unique = true, nullable = false)
    @Type(type = "uuid-char")
    private UUID id;

    @ManyToOne(cascade = CascadeType.REMOVE)
    @PrimaryKeyJoinColumn(name = "conversation_id", referencedColumnName = "id")
    private Conversation conversation;

    @ManyToOne(optional = false)
    @PrimaryKeyJoinColumn(name = "user_id", referencedColumnName = "id", foreignKey = @ForeignKey(name = "fk_user_id"))
    private User user;

}

我希望由于ConversationUser.user设置的方式,如果我尝试运行以下测试,它将产生异常。但是,此测试失败并且不会生成异常。我检查了数据库,并且正在插入该行。

@Test(expected = Exception.class)
public void testFakeAttendeeOfConversation() {
    UserModel fakeUserModel = generateRandomUser();
    fakeUserModel.setId(UUID.randomUUID());
    conversationService.createConversation(new JwtUser(userA), Collections.singleton(fakeUserModel.getId()));
}

调用 ConversationUser 存储库接口的函数(extends JpaRepository<ConversationUser, UUID>)如下..

@Transactional
public void addUserToConversation(JwtUser jwtRequestUser, Conversation conversation, UUID attendeeId) {
    User attendee = User.builder().id(attendeeId).build();
    ConversationUser conversationUser = ConversationUser.builder()
            .conversation(conversation)
            .user(attendee)
            .build();
    conversationUserRepository.save(conversationUser);
}

有谁知道为什么ConversationUser即使其中引用的用户在数据库中不存在,我也可以插入任何内容?

标签: javaspringhibernatespring-bootjpa

解决方案


推荐阅读