web-dev-qa-db-fra.com

org.hibernate.MappingException: impossible de déterminer le type pour: Java.util.Set

Bien que cette question ait été posée à plusieurs reprises et que j'ai déjà utilisé toute la suggestion, je reçois néanmoins cette erreur.

Le User.Java est

@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;
    }
}

Et le Role.Java est

@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;
    }
}

C’est la première fois que je tente une annotation en veille prolongée avec JPA. Donc, toutes les suggestions seront très utiles. 

Pour hibernate, les dépendances de pom.xml sont les suivantes:

    <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>

Je n'ai aucune idée de la faute.

Merci.

70
Tapas Bose

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 comme ci-dessus.

5
Tapas Bose

J'ai le même problème avec la colonne @ManyToOne. C'était résolu ... d'une manière stupide. J'avais toutes les autres annotations pour les méthodes getter publiques, car elles avaient été remplacées par la classe parent. Mais le dernier champ a été annoté pour la variable privée, comme dans toutes les autres classes de mon projet. J'ai donc la même MappingException sans la raison.

Solution: J'ai placé toutes les annotations dans les méthodes de lecture publiques. Je suppose qu'Hibernate ne peut pas gérer les cas où des annotations pour des champs privés et des getters publics sont mélangés dans une classe.

76
Avadhuta

L'ajout du @ElementCollection au champ Liste a résolu ce problème:

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

Je suppose que vous utilisez un Set<Role> dans la classe User annotée avec @OneToMany. Ce qui signifie qu'une User a plusieurs Roles. Mais sur le même champ, vous utilisez l'annotation @Column qui n'a aucun sens. Les relations un à plusieurs sont gérées à l'aide d'une table de jointure séparée ou d'une colonne de jointure du côté multiple, qui dans ce cas serait la classe de rôle. Utiliser @JoinColumn au lieu de @Column résoudrait probablement le problème, mais cela semble sémantiquement faux. J'imagine que la relation entre le rôle et l'utilisateur devrait être multiple.

15
whiskeysierra

Ne dites pas que votre mappage est correct ou faux, mais je pense qu'Hibernate souhaite une instance de l'ensemble où vous déclarez le champ.

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

Si ce problème venait d’aujourd’hui et que j’avais découvert par inadvertance que j’avais omis l’annotation @ManyToMany au-dessus de l’annotation @JoinTable. 

4
Mark

J'avais un problème similaire. J'ai trouvé le problème en mélangeant les annotations, certaines au-dessus des attributs et certaines au-dessus des méthodes publiques. Je viens de mettre tous les ci-dessus des attributs et cela fonctionne.

2
Melissa Jiménez

Vous devrez peut-être simplement ajouter des annotations @Transient sur les rôles pour ne pas sérialiser l'ensemble.

Pourquoi Java a-t-il des champs transitoires?

1
Mark

J'ai eu un problème similaire où je recevais une erreur pour un membre de la classe qui n'a pas été mappé à la colonne de base de données, il s'agissait simplement d'un titulaire pour la liste d'une autre entité. J'ai changé List en ArrayList et l'erreur est partie. Je sais, je ne devrais vraiment pas faire cela dans une entité cartographiée, et c'est à cela que servent les DTO. Je voulais juste partager si quelqu'un trouve ce fil et que les réponses ci-dessus ne s'appliquent pas et ne les aident pas.

0
Ginja Ninja