我有一个基本的JPA实体,所有其他实体都从该实体派生。但是,当我启动应用程序时,它给出了IllegalArgumentException:此类[class demo.rbacapp.entity.UserAccountRole类]没有定义IdClass。
我正在尝试使用@Embeddable主键UserAccountRolePk在UserAccount和Role之间创建多对多关系。
如果我想念什么,谁能指出我?当我在这里拥有EmbeddedId时,抱怨缺少IdClass的原因是什么。
@MappedSuperclass
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "id", nullable = false)
private long id;
@UpdateTimestamp @Column(name = "update_timestamp", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date updateTimestamp;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getUpdateTimestamp() {
return updateTimestamp;
}
public void setUpdateTimestamp(Date updateTimestamp) {
this.updateTimestamp = updateTimestamp;
}
}
这些是实际的实体。
@Entity @Table(name = "USER_ACCOUNT")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@AttributeOverride(name = "id", column = @Column(name="user_id"))
public class UserAccount extends BaseEntity {
private static final long serialVersionUID = 1234567890L;
@Column(name = "username", unique = true) //username has to be unique
private String username;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "age")
private int age;
@Column(name = "gender")
private String gender;
@Column(name = "password")
private String password;
@OneToMany(mappedBy = "userAccountRolePk.role", cascade = CascadeType.ALL)
private Set<UserAccountRole> userAccountRoles = new HashSet<>();
public Set<UserAccountRole> getUserAccountRoles() {
return userAccountRoles;
}
public void setUserAccountRoles(Set<UserAccountRole> r) {
this.userAccountRoles = r;
}
public void addUserAccountRoles(UserAccountRole r) {
this.userAccountRoles.add(r);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
@Entity
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@AttributeOverride(name = "id", column = @Column(name="role_id"))
public class Role extends BaseEntity {
private static final long serialVersionUID = 1234567893L;
@Column(name = "name")
private String name;
@Column(name = "description")
private String description;
/* if true, then cannot be updated by users or rest api */
@Column(name = "immutable")
private boolean immutable;
@OneToMany(mappedBy = "rolePriviledgePk.role", cascade = CascadeType.ALL)
private Set<RolePriviledge> rolePriviledges = new HashSet<>();
public Set<RolePriviledge> getRolePriviledges() {
return rolePriviledges;
}
public void setRolePriviledges(Set<RolePriviledge> rolePriviledges) {
this.rolePriviledges = rolePriviledges;
}
public void addRolePriviledges(RolePriviledge rolePriviledge) {
this.rolePriviledges.add(rolePriviledge);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isImmutable() {
return immutable;
}
public void setImmutable(boolean immutable) {
this.immutable = immutable;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
}
这是联接类(多对多)。
@Entity
@Table(name = "USERACCOUNT_ROLES")
@AssociationOverrides(
{ @AssociationOverride(name = "userAccountRolePk.userAccount",
joinColumns = @JoinColumn(name = "USER_ID")),
@AssociationOverride(name = "userAccountRolePk.role",
joinColumns = @JoinColumn(name = "ROLE_ID"))
})
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class UserAccountRole extends BaseEntity {
//composite primary key
@EmbeddedId
private UserAccountRolePk userAccountRolePk = new UserAccountRolePk();
//additional fields if any (updateTimeStamp inherited from BaseEntity)
private boolean immutable;
public UserAccountRolePk getUserAccountRolePk() {
return userAccountRolePk;
}
public void setUserAccountRolePk(UserAccountRolePk pk) {
this.userAccountRolePk = pk;
}
@Transient
public UserAccount getUserAccount() {
return getUserAccountRolePk().getUserAccount();
}
public void setUserAccount(UserAccount u) {
getUserAccountRolePk().setUserAccount(u);
}
@Transient
public Role getRole() {
return getUserAccountRolePk().getRole();
}
public void setRole(Role p) {
getUserAccountRolePk().setRole(p);
}
public boolean isImmutable() {
return immutable;
}
public void setImmutable(boolean immutable) {
this.immutable = immutable;
}
}
这是主键类。
@Embeddable
public class UserAccountRolePk {
@ManyToOne(cascade = CascadeType.ALL)
private UserAccount userAccount;
@ManyToOne(cascade = CascadeType.ALL)
private Role role;
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public UserAccount getUserAccount() {
return userAccount;
}
public void setUserAccount(UserAccount x) {
this.userAccount = x;
}
public boolean equals(Object o) {
if(o == null || o.getClass() != this.getClass()) {
return false;
}
UserAccountRolePk pk = (UserAccountRolePk) o;
if(this.getRole().equals(pk.getRole()) && this.getUserAccount().equals(pk.getUserAccount())) {
return true;
}
return false;
}
public int hashCode() {
return new Long(this.getRole().getId() + this.getUserAccount().getId()).hashCode();
}
}
启动时收到异常:
java.lang.IllegalArgumentException: This class [class demo.rbacapp.entity.UserAccountRole] does not define an IdClass
at org.hibernate.jpa.internal.metamodel.AbstractIdentifiableType.getIdClassAttributes (AbstractIdentifiableType.java:183)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation$IdMetadata.<init> (JpaMetamodelEntityInformation.java:253)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init> (JpaMetamodelEntityInformation.java:84)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation (JpaEntityInformationSupport.java:68)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation (JpaRepositoryFactory.java:173)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository (JpaRepositoryFactory.java:106)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository (JpaRepositoryFactory.java:88)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository (RepositoryFactorySupport.java:198)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.initAndReturn (RepositoryFactoryBeanSupport.java:277)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet (RepositoryFactoryBeanSupport.java:263)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet (JpaRepositoryFactoryBean.java:101)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods (AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean (AbstractAutowireCapableBeanFactory.java:1624)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean (AbstractAutowireCapableBeanFactory.java:555)