postgresql 外键是复合主键的一对多Map

nwo49xxi  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(133)

我正在尝试为以下关系创建HibernateMap:

CREATE TABLE users (
    id   UUID PRIMARY KEY,
    name TEXT NOT NULL
);

CREATE TABLE user_roles (
    user_id UUID NOT NULL,
    role    TEXT NOT NULL,

    CONSTRAINT pk_user_roles UNIQUE(user_id, role),
    CONSTRAINT fk_user_roles_users FOREIGN KEY(user_id) REFERENCES users(id)
);

我也想用户实体能够列出他们分配的角色。我得出了以下结论:

@Entity
@Table(name="users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    @Column(name="id")
    private UUID id;

    @Column(name="name")
    private String name;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "user_id", nullable = false)
    @BatchSize(size=10)
    private Set<UserRole> roles = new HashSet<>();

    // ...
}
@Entity
@Table(name="user_roles")
@IdClass(UserRoleId.class)
public class UserRole {
    @Id
    @Column(name = "user_id", nullable = false)
    private UUID userId;  // I don't need this field here, had to add it because Hibernate requires it

    @Id
    @Column(name="role", nullable = false)
    private String role;

    // ...
}
public class UserRoleId implements Serializable {
    private UUID userId;

    private String role;

    // ...
}

这似乎是工作,但当我试图添加新的角色到现有的用户实体,然后持久化这个实体比我得到以下:

org.hibernate.exception.DataException: could not execute statement [No value specified for parameter 3.] [insert into user_roles (user_id,role,user_id) values (?,?,?)]

有没有人知道如何实现我想要的?我试着将人工自动递增键添加到UserRole并使其成为主键。它起作用了,但它看起来像一个丑陋的变通方法。
顺便说一句:我使用的是Quarkus框架附带的Hibernate 6.x。

3pvhb19x

3pvhb19x1#

好吧,我想我明白了。第一个Map需要像这样改变

@Entity
@Table(name="users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.UUID)
    @Column(name="id")
    private UUID id;

    @Column(name="name")
    private String name;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    @BatchSize(size=10)
    private List<UserRole> roles = new ArrayList<>();
}
@Entity
@Table(name="user_roles")
@IdClass(UserRoleId.class)
public class UserRole {
    @Id
    @ManyToOne
    @JoinColumn(name="user_id", nullable = false)
    private User user;

    @Id
    @Column(name="role", nullable = false)
    private String role;
}

但问题本身在于实体的持久化方式

var role = new UserRole();
role.setUser(user);  // <-- this line was missing
role.setRole(roleName);
user.getRoles().add(role);

entityManager.merge(user);

相关问题