“非法尝试将非集合映射为 @OneToMany、@ManyToMany 或 @CollectionOfElements”

Posted

技术标签:

【中文标题】“非法尝试将非集合映射为 @OneToMany、@ManyToMany 或 @CollectionOfElements”【英文标题】:“Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements” 【发布时间】:2017-10-30 17:02:47 【问题描述】:

早上好 ***,

我的问题是它给了我错误:

创建会话工厂失败 object.org.hibernate.AnnotationException:非法尝试映射非 集合为 @OneToMany、@ManyToMany 或 @CollectionOfElements: nl.scalda.pasimo.model.employeemanagement.EducationTeam.coachGroups

你知道为什么吗?

@OneToMany(cascade=CascadeType.ALL, targetEntity=CoachGroup.class)
@JoinColumn(name="id")
private TreeSet<CoachGroup> coachGroups = new TreeSet<>();
private SessionFactory factory;

private void initialiseFactory() 
    try 
        factory = new Configuration().configure().buildSessionFactory();
     catch (Throwable ex) 
        System.err.println("Failed to create sessionFactory object." + ex);
        throw new ExceptionInInitializerError(ex);
    

【问题讨论】:

你为什么用TreeSet而不是Set?! 【参考方案1】:

异常很简单,说:非法尝试将非集合映射为@OneToMany、@ManyToMany 或@CollectionOfElements,所以原因在这里很明显,如果我们看看@ 987654321@它明确指出:

作为要求,必须将持久集合值字段声明为接口类型(参见示例 7.2,“使用 @OneToMany 和 @JoinColumn 的集合映射”)。实际的接口可能是java.util.Setjava.util.Collectionjava.util.Listjava.util.Mapjava.util.SortedSetjava.util.SortedMap...

您使用了TreeSet,它是Set&lt;E&gt;SortedSet&lt;E&gt; 接口的 实现。所以你的实际映射不适用于TreeSet,你应该使用Set&lt;CoachGroup&gt;而不是TreeSet&lt;CoachGroup&gt;

private Set<CoachGroup> coachGroups = new HashSet<CoachGroup>();

【讨论】:

【参考方案2】:

您应该映射到接口而不是实现。这个:

@OneToMany(cascade=CascadeType.ALL, targetEntity=CoachGroup.class)
@JoinColumn(name="id")
private TreeSet<CoachGroup> coachGroups = new TreeSet<>();

应该是(也替换了 TreeSet,因为这里一个 HashSet 就足够了):

@OneToMany(cascade=CascadeType.ALL, targetEntity=CoachGroup.class)
@JoinColumn(name="id")
private Set<CoachGroup> coachGroups = new HashSet<>();

【讨论】:

【参考方案3】:

发生此异常的另一个可能原因是使用非集合对象 @ManyToMany@OneToMany 映射或将集合对象用于@ManyToOne@OneToOne 映射。以下所有示例均不正确。

不正确

 @ManyToMany
 private User user;

 @ManyToOne
 private User user;

 @OneToOne
 private List<User> users;

 @ManyToOne
 private List<User> users;

【讨论】:

感谢您的回答...我遇到了同样的问题@ManyToMany private User user【参考方案4】:

您不能将集合字段保存为具体类。

知道了,

作为要求,必须声明持久的集合值字段 作为接口类型(参见示例 7.2,“使用 @OneToMany 和 @JoinColumn”)。实际的界面可能是 java.util.Set、java.util.Collection、java.util.List、java.util.Map、 java.util.SortedSet、java.util.SortedMap 或任何你喜欢的 (“你喜欢的任何东西”意味着你必须编写一个实现 org.hibernate.usertype.UserCollectionType)。

来自Chapter 7. Collection Mapping。

您可以使用以下代码来保存排序集:

请务必阅读 cmets

@OneToMany(cascade=CascadeType.ALL) //Removed targetEntity, as you are already using generics.
@JoinColumn(name="team_id") // Use this name as to show the presence of foreign key of EducationTeam in CoachGroup.
@SortNatural // Make sure that your CoachGroup Entity has implemented Comparable<CoachGroup> interface which wii be used while sorting.
private SortedSet<CoachGroup> coachGroups = new TreeSet<>();

【讨论】:

【参考方案5】:

您不能在实体字段声明中使用具体实现。您可以使用以下其中一项:

java.util.List java.util.Set java.util.Collection

所以在你的情况下它必须是:

@OneToMany(cascade=CascadeType.ALL, targetEntity=CoachGroup.class)
@JoinColumn(name="id")
private Set<CoachGroup> coachGroups = new TreeSet<>();

【讨论】:

以上是关于“非法尝试将非集合映射为 @OneToMany、@ManyToMany 或 @CollectionOfElements”的主要内容,如果未能解决你的问题,请参考以下文章

给出一对五和多对一的关系有啥问题。为啥会发生这个错误