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

“Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements”

早上好 Whosebug,

我遇到了错误:

Failed to create sessionFactory object.org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @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);
    }
}

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

@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<>();

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

  • 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<>();

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

知道了,

As a requirement persistent collection-valued fields must be declared as an interface type (see Example 7.2, “Collection mapping using @OneToMany and @JoinColumn”). The actual interface might be java.util.Set, java.util.Collection, java.util.List, java.util.Map, java.util.SortedSet, java.util.SortedMap or anything you like ("anything you like" means you will have to write an implementation of org.hibernate.usertype.UserCollectionType).

来自 Chapter 7. Collection Mapping.

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

Please do read the comments too

@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<>();

异常很简单,它说:非法尝试将非集合映射为@OneToMany、@ManyToMany 或@CollectionOfElements,所以原因很明显,如果我们采取看一下 Hibernate Collection mapping documentation 它清楚地指出:

As a requirement persistent collection-valued fields must be declared as an interface type (see Example 7.2, “Collection mapping using @OneToMany and @JoinColumn”). The actual interface might be java.util.Set, java.util.Collection, java.util.List, java.util.Map, java.util.SortedSet, java.util.SortedMap...

并且您使用了 TreeSet,它是 classSet<E>SortedSet<E> 接口的实现。所以您的实际映射不适用于 TreeSet,您应该使用 Set<CoachGroup> 而不是 TreeSet<CoachGroup>:

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

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

不正确

 @ManyToMany
 private User user;

 @ManyToOne
 private User user;

 @OneToOne
 private List<User> users;

 @ManyToOne
 private List<User> users;