Org.hibernate.MappingException: Не удалось определить тип для: java.util.Set
Хотя этот вопрос задавался много раз, и я уже использовал все предложения, но все же получаю эту ошибку.
Пользователь User.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>
У меня нет никакой информации об ошибке.
Спасибо.
Ответы
Ответ 1
Решение:
@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, как указано выше.
Ответ 2
У меня такая же проблема с столбцом @ManyToOne
. Это было решено... глупо. У меня были все другие аннотации для общедоступных методов getter, потому что они были переопределены из родительского класса. Но последнее поле было аннотировано для частной переменной, как и во всех других классах моего проекта. Таким образом, я получил тот же MappingException
без причины.
Решение. Я разместил все аннотации в общедоступных методах получения. Я полагаю, Hibernate не может обрабатывать случаи, когда аннотации для частных полей и публичных геттеров смешиваются в одном классе.
Ответ 3
Добавление поля @ElementCollection
в список позволило решить эту проблему:
@Column
@ElementCollection(targetClass=Integer.class)
private List<Integer> countries;
Ответ 4
Я предполагаю, что вы используете Set<Role>
в классе User
, аннотированный с помощью @OneToMany
. Это означает, что один User
имеет много Role
s. Но в том же поле вы используете аннотацию @Column
, которая не имеет смысла. Управление "один ко многим" управляется с помощью отдельной таблицы соединений или столбца объединения на стороне, которая в этом случае будет классом Role. Использование @JoinColumn
вместо @Column
, вероятно, устранит проблему, но кажется семантически неправильным. Я полагаю, что отношение между ролью и пользователем должно быть много-ко-многим.
Ответ 5
Не сказать, что ваше сопоставление правильное или неправильное, но я думаю, что hibernate хочет экземпляр набора, в котором вы объявляете поле.
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER)
//@ElementCollection(targetClass=Role.class)
@Column(name = "ROLE_ID")
private Set<Role> roles = new HashSet<Role>();
Ответ 6
Вам просто нужно добавить аннотации @Transient
к ролям, чтобы не сериализовать набор.
Почему Java имеет переходные поля?
Ответ 7
Если бы эта проблема появилась сегодня и обнаружила, что я случайно отказался от аннотации @ManyToMany над аннотацией @JoinTable.
Ответ 8
У меня была аналогичная проблема, я обнаружил, что я смешивал аннотации с некоторыми из них над атрибутами, а некоторые из них - над общедоступными методами. Я просто положил все из них выше атрибутов, и он работает.
Ответ 9
У меня была аналогичная проблема, когда я получал сообщение об ошибке для члена класса, который не был сопоставлен столбцу db, он был просто владельцем списка другого объекта. Я изменил List на ArrayList, и ошибка исчезла. Я знаю, я действительно не должен этого делать в сопоставленной сущности и для чего нужен DTO. Просто хотел поделиться, если кто-то найдет этот поток, и ответы выше не применяются или не помогают.