Spring Boot JPA @JoinTable 与现有映射表忽略 @GeneratedValue
Posted
技术标签:
【中文标题】Spring Boot JPA @JoinTable 与现有映射表忽略 @GeneratedValue【英文标题】:Spring Boot JPA @JoinTable with existing mapping table ignoring @GeneratedValue 【发布时间】:2017-09-30 16:50:39 【问题描述】:我正在尝试在 User
和 UserRole
两个实体之间创建 ManyToMany
关系。
我需要在映射表UserToRoleMapping
中添加一些额外的列,因此我创建了一个用于映射表的实体,其中包含额外的列(如createdDate
或isActive
)。
现在的问题是 JPA 忽略映射表 userRoleMappingId
列上的 @Id
和 @GeneratedValue
注释,并使用 userId, roleId
创建复合主键。没关系。由于userRoleMappingId
列不是主键,我不再需要它,但是一旦我删除它,JPA 就会抱怨它需要一个带有@Id
注释的列。
即使我保持原样,当使用spring data repository for User
保存带有某些角色的User
时,它会抛出userRoleMappingId
列不能为空的异常,因为存储库不会尝试为映射表生成ID,它被设置为not null
。
理想情况下,我希望在带有序列生成器的映射表中拥有一个主键。
创建带有额外列的 JoinTable 的正确方法是 实体?
这是一个包含示例代码的 github 存储库,用于重现问题。
https://github.com/ConsciousObserver/SpringBootJoinTableIssue.git
以下是实体代码
@Entity
@SequenceGenerator(name="USER_SEQ")
class User
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USER_SEQ")
private long userId;
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name="UserRoleMapping", joinColumns=@JoinColumn(name="userId"), inverseJoinColumns=@JoinColumn(name="roleId"))
private Set<Role> roles;
/*getters and setters */
@Entity
@SequenceGenerator(name="ROLE_SEQ")
class Role
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ROLE_SEQ")
private long roleId;
/*getters and setters */
@Entity
@SequenceGenerator(name="USER_ROLE_SEQ")
class UserRoleMapping
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="USER_ROLE_SEQ")
private long userRoleMappingId;
@OneToOne
@JoinColumn(name="userId")
private User user;
@OneToOne
@JoinColumn(name="roleId")
private Role role;
private Date createdDate;
/*getters and setters */
【问题讨论】:
【参考方案1】:实体声明未反映帖子中提到的所需关系。它们应该声明如下:
用户实体
@Entity
public class User
@Id
private long id;
@OneToMany(mappedBy = "user")
private List<UserRole> roles;
用户角色实体
@Entity
public class UserRole
@Id
private long id;
@ManyToOne
@JoinColumn(name="userId")
private User user;
@ManyToOne
@JoinColumn(name="roleId")
private Role role;
这将确保每个User
可以有多个Role
s,同样每个Role
可以分配给多个User
s,这样如果User
s 和Role
s 都可以一起查看,就会看到多对多的映射。
【讨论】:
我需要User
和Role
之间的@ManyToMany
关系,因此需要@JoinTable
。请再次检查问题。
@11thdimension,你会得到一个@ManyToMany
与我的答案的关系(每个用户可以有角色,每个角色可以分配给许多用户)。仔细阅读答案并尝试一下。使用映射表,@ManyToMany
根本不起作用,这似乎让您感到困惑。
在您的实体中(userId,roleId)之间的映射将存储在哪里?
好的,我没有看到你使用UserRole
作为映射表,我的用户表中是否必须有映射表的名称?我不能直接获取角色列表吗?
如果你使用Java 8,在User
类的getRoles
方法中应该可以直接编码为return roles.stream().map(UserRole::getRole).collect(Collectors::toList);
。如果你不使用Java 8,方法会稍微更长,但可以轻松应用相同的翻译。以上是关于Spring Boot JPA @JoinTable 与现有映射表忽略 @GeneratedValue的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot(十五):spring boot+jpa+thymeleaf增删改查示例
[Spring Boot] Adding JPA and Spring Data JPA