org.hibernate.MappingException:无法确定类型:java.util.Set [重复]

Posted

技术标签:

【中文标题】org.hibernate.MappingException:无法确定类型:java.util.Set [重复]【英文标题】:org.hibernate.MappingException: Could not determine type for: java.util.Set [duplicate] 【发布时间】:2011-09-04 01:57:15 【问题描述】:

虽然这个问题被问了很多次并且我已经使用了所有的建议,但我仍然收到这个错误。

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>

我不知道故障所在。

谢谢。

【问题讨论】:

在这种情况下,您必须仅将 @ManyToOne 与 @JoinColumn 一起使用,因为 Role 是一个实体。仅当集合包含基本类型(整数、字符串、日期等)或可嵌入类型时,才使用 @ElementCollection 和 @Column。如果需要,请参阅 JPA 2.0 规范中的示例。您正在组合从未一起使用的注释,这可能是问题的根源。 【参考方案1】:

@ManyToOne 列也有同样的问题。它被解决了......以愚蠢的方式。我有公共 getter 方法的所有其他注释,因为它们被父类覆盖。但是最后一个字段被注释为私有变量,就像我项目中的所有其他类一样。所以我毫无理由地得到了相同的MappingException

解决方案:我将所有注释都放在公共 getter 方法中。我想,当私有字段和公共 getter 的注释混合在一个类中时,Hibernate 无法处理这种情况。

【讨论】:

【参考方案2】:

@ElementCollection 添加到列表字段解决了这个问题:

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

【讨论】:

什么?这与问题无关。 为我解决了这个问题,甚至没有指定 targetClass :) (targetClass=Integer.class) 在这种情况下不需要。仅当您的列表是泛型类型时才需要这样做 您不需要在每个数据成员上默认指定@Column @Column【参考方案3】:

我猜你在User 类中使用Set&lt;Role&gt;,并用@OneToMany 注释。这意味着一个User 有许多Roles。但是在同一个字段上,您使用 @Column 注释,这是没有意义的。一对多关系使用单独的连接表或多方连接列进行管理,在本例中为 Role 类。使用@JoinColumn 而不是@Column 可能会解决这个问题,但它似乎在语义上是错误的。我猜角色和用户之间的关系应该是多对多的。

【讨论】:

@ElementCollection 在那里看起来也很奇怪。目的是什么? 更改为 @OneToMany(cascade=CascadeType.ALL, targetEntity=Role.class, mappedBy="user", fetch = FetchType.EAGER) @JoinColumn(name="ROLE_ID") 私有集 角色;没有解决问题。我看到其他一些线程建议使用@ElementCollection,这就是我使用它的原因。 elementCollection 不是用于组件的吗?生命周期遵循拥有实体的对象?【参考方案4】:

今天刚遇到这个问题,发现我无意中遗漏了@JoinTable 注释上方的@ManyToMany 注释。

【讨论】:

【参考方案5】:

不是说你的映射是正确还是错误,但我认为 hibernate 想要一个你声明字段的集合的实例。

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

【讨论】:

我是按照你的指示去做的。但没有解决。如果你愿意,我可以发布完整的堆栈跟踪。 角色集中不需要使用@ElementCollection,因为角色是一个实体。在这种情况下,您只能使用 @ManyToOne。 JPA 2.0 规范明确指出 @EllementCollection 用于基本类型和可嵌入对象。此外,您必须使用@JoinColumn 指定列信息,而不是@Column。后者将与@ElementCollection 一起使用,但不能与@ManyToOne 一起使用。 确定发布堆栈跟踪和 edalorzo 我知道你是对的【参考方案6】:

我遇到了类似的问题,我发现我将注释混合在一起的问题,其中一些在属性之上,一些在公共方法之上。我只是将它们全部放在属性之上,它就可以工作。

【讨论】:

这里也一样。你让我免于数小时的调试。谢谢!【参考方案7】:

解决方案:

@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 同上。

【讨论】:

如果您告诉需要更改的内容(并解释原因)而不是发布完整的代码会更好。必须逐行比较两个文件才能发现差异。 比较文件,我发现以下差异: 1.他在类中添加了@Access(AccessType.FIELD) 2. Set 角色上的@ElementColection 已替换为@JoinTable (...)【参考方案8】:

您可能只需要在角色上添加@Transient 注释即可不序列化集合。

Why does Java have transient fields?

【讨论】:

【参考方案9】:

我遇到了一个类似的问题,我收到了一个未映射到 db 列的类成员的错误,它只是另一个实体列表的持有者。我将 List 更改为 ArrayList 并且错误消失了。我知道,我真的不应该在映射实体中这样做,这就是 DTO 的用途。只是想分享一下,以防有人发现这个帖子并且上面的答案不适用或没有帮助。

【讨论】:

以上是关于org.hibernate.MappingException:无法确定类型:java.util.Set [重复]的主要内容,如果未能解决你的问题,请参考以下文章