异常: 无法确定 java.util. Set 的类型

虽然这个问题问了很多次,我已经用了所有的建议,但是我还是得到了这个错误。

Java 是

@Entity
@Table(name = "USER")
public class User implements UserDetails, Serializable {


private static final long serialVersionUID = 2L;


@Id
@Column(name = "USER_ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "USERNAME")
private String username;
@Column(name = "PASSWORD")
private String password;
@Column(name = "NAME")
private String name;
@Column(name = "EMAIL")
private String email;
@Column(name = "LOCKED")
private boolean locked;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
@ElementCollection(targetClass=Role.class)
@Column(name = "ROLE_ID")
private Set<Role> roles;


@Override
public GrantedAuthority[] getAuthorities() {
List<GrantedAuthorityImpl> list = new ArrayList<GrantedAuthorityImpl>(0);
for (Role role : roles) {
list.add(new GrantedAuthorityImpl(role.getRole()));
}
return (GrantedAuthority[]) list.toArray(new GrantedAuthority[list.size()]);
}


@Override
public boolean isAccountNonExpired() {
return true;
}


@Override
public boolean isAccountNonLocked() {
return !isLocked();
}


@Override
public boolean isCredentialsNonExpired() {
return true;
}


@Override
public boolean isEnabled() {
return true;
}


public long getId() {
return id;
}


public void setId(long id) {
this.id = id;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public String getEmail() {
return email;
}


public void setEmail(String email) {
this.email = email;
}


public boolean isLocked() {
return locked;
}


public void setLocked(boolean locked) {
this.locked = locked;
}


@Override
public String getUsername() {
return username;
}


public void setUsername(String username) {
this.username = username;
}


@Override
public String getPassword() {
return password;
}


public void setPassword(String password) {
this.password = password;
}


public void setRoles(Set<Role> roles) {
this.roles = roles;
}


public Set<Role> getRoles() {
return roles;
}
}

而 Role.java 是

@Entity
@Table(name="ROLE")
public class Role implements Serializable {


@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="ROLE_ID")
private long id;
@Column(name="USERNAME")
private String username;
@Column(name="ROLE")
private String role;




public long getId() {
return id;
}


public void setId(long id) {
this.id = id;
}


public String getUsername() {
return username;
}


public void setUsername(String username) {
this.username = username;
}


public String getRole() {
return role;
}


public void setRole(String role) {
this.role = role;
}
}

这是我第一次尝试使用 JPA 来冬眠注释。所以任何建议都会非常有帮助。

对于休眠,pom.xml 的依赖项是:

    <dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.5.4-Final</version>
<type>pom</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.5.4-Final</version>
<type>jar</type>
<scope>compile</scope>
</dependency>


<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.5.4-Final</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.1.0.GA</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.5.4-Final</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

我不知道错在哪里。

谢谢。

221753 次浏览

My guess is you are using a Set<Role> in the User class annotated with @OneToMany. Which means one User has many Roles. But on the same field you use the @Column annotation which makes no sense. One-to-many relationships are managed using a separate join table or a join column on the many side, which in this case would be the Role class. Using @JoinColumn instead of @Column would probably fix the issue, but it seems semantically wrong. I guess the relationship between role and user should be many-to-many.

Not saying your mapping is correct or wrong but I think hibernate wants a instance of the set where you declare the field.

@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
//@ElementCollection(targetClass=Role.class)
@Column(name = "ROLE_ID")
private Set<Role> roles = new HashSet<Role>();

Solution:

@Entity
@Table(name = "USER")
@Access(AccessType.FIELD)
public class User implements UserDetails, Serializable {


private static final long serialVersionUID = 2L;


@Id
@Column(name = "USER_ID", updatable=false, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;


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


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


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


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


@Column(name = "LOCKED")
private boolean locked;


@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Role.class)
@JoinTable(name = "USER_ROLE", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
private Set<Role> roles;


@Override
public GrantedAuthority[] getAuthorities() {
List<GrantedAuthorityImpl> list = new ArrayList<GrantedAuthorityImpl>(0);
for (Role role : roles) {
list.add(new GrantedAuthorityImpl(role.getRole()));
}
return (GrantedAuthority[]) list.toArray(new GrantedAuthority[list.size()]);
}


@Override
public boolean isAccountNonExpired() {
return true;
}


@Override
public boolean isAccountNonLocked() {
return !isLocked();
}


@Override
public boolean isCredentialsNonExpired() {
return true;
}


@Override
public boolean isEnabled() {
return true;
}


public long getId() {
return id;
}


public void setId(long id) {
this.id = id;
}


@Override
public String getUsername() {
return username;
}


public void setUsername(String username) {
this.username = username;
}


@Override
public String getPassword() {
return password;
}


public void setPassword(String password) {
this.password = password;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}


public String getEmail() {
return email;
}


public void setEmail(String email) {
this.email = email;
}


public boolean isLocked() {
return locked;
}


public void setLocked(boolean locked) {
this.locked = locked;
}


public Set<Role> getRoles() {
return roles;
}


public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}

Role.java same as above.

Adding the @ElementCollection to the List field solved this issue:

@Column
@ElementCollection(targetClass=Integer.class)
private List<Integer> countries;

I got the same problem with @ManyToOne column. It was solved... in stupid way. I had all other annotations for public getter methods, because they were overridden from parent class. But last field was annotated for private variable like in all other classes in my project. So I got the same MappingException without the reason.

Solution: I placed all annotations at public getter methods. I suppose, Hibernate can't handle cases, when annotations for private fields and public getters are mixed in one class.

You may just need to add @Transient annotations on roles to not serialize the set.

Why does Java have transient fields?

I had a similar issue where I was getting an error for a member in the class that wasn't mapped to the db column, it was just a holder for a List of another entity. I changed List to ArrayList and the error went away. I know, I really shouldn't do that in a mapped entity, and that's what DTO's are for. Just wanted to share in case someone finds this thread and the answers above don't apply or help.

Had this issue just today and discovered that I inadvertently left off the @ManyToMany annotation above the @JoinTable annotation.

I had similar problem I found the issue I was mixing the annotations some of them above the attributes and some of them above public methods. I just put all of them above attributes and it works.