【问题标题】:org.hibernate.MappingException: Could not determine type for: java.util.List, at table: College, for columns: [org.hibernate.mapping.Column(students)]org.hibernate.MappingException:无法确定类型:java.util.List,在表:College,列:[org.hibernate.mapping.Column(students)]
【发布时间】:2011-04-16 00:13:38
【问题描述】:

我将 Hibernate 用于我项目中的所有 CRUD 操作。它不适用于一对多和多对一关系。它给了我以下错误。

org.hibernate.MappingException: Could not determine type for: java.util.List, at table: College, for columns: [org.hibernate.mapping.Column(students)]

然后我又经历了这个video tutorial。一开始对我来说很简单。但是,我不能让它工作。现在也是,说

org.hibernate.MappingException: Could not determine type for: java.util.List, at table: College, for columns: [org.hibernate.mapping.Column(students)]

我在互联网上进行了一些搜索,有人告诉its a bug in Hibernate,有人说,通过添加@GenereatedValue,这个错误将被清除,但它对我不起作用。

College.java

@Entity
public class College {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int collegeId;
private String collegeName;


private List<Student> students;

@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)
public List<Student> getStudents() {
    return students;
}
public void setStudents(List<Student> students) {
    this.students = students;
}//Other gettters & setters omitted

Student.java

@Entity
public class Student {


@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int studentId;
private String studentName;


private College college;

@ManyToOne
@JoinColumn(name="collegeId")
public College getCollege() {
    return college;
}
public void setCollege(College college) {
    this.college = college;
}//Other gettters & setters omitted

Main.java:

public class Main {

private static org.hibernate.SessionFactory sessionFactory;

  public static SessionFactory getSessionFactory() {
    if (sessionFactory == null) {
      initSessionFactory();
    }
    return sessionFactory;
  }

  private static synchronized void initSessionFactory() {
    sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();

  }

  public static Session getSession() {
    return getSessionFactory().openSession();
  }

  public static void main (String[] args) {
                Session session = getSession();
        Transaction transaction = session.beginTransaction();
        College college = new College();
        college.setCollegeName("Dr.MCET");

        Student student1 = new Student();
        student1.setStudentName("Peter");

        Student student2 = new Student();
        student2.setStudentName("John");

        student1.setCollege(college);
        student2.setCollege(college);



        session.save(student1);
        session.save(student2);
        transaction.commit();
  }


}

控制台:

 Exception in thread "main" org.hibernate.MappingException: Could not determine type  for: java.util.List, at table: College, for columns:  [org.hibernate.mapping.Column(students)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:306)
at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:290)
at org.hibernate.mapping.Property.isValid(Property.java:217)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:463)
at org.hibernate.mapping.RootClass.validate(RootClass.java:235)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1330)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1833)
at test.hibernate.Main.initSessionFactory(Main.java:22)
at test.hibernate.Main.getSessionFactory(Main.java:16)
at test.hibernate.Main.getSession(Main.java:27)
at test.hibernate.Main.main(Main.java:43)

XML:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
    <!-- Database connection settings -->
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/dummy</property>
    <property name="connection.username">root</property>
    <property name="connection.password">1234</property>
    <!-- JDBC connection pool (use the built-in) -->
    <property name="connection.pool_size">1</property>
    <!-- SQL dialect -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- Enable Hibernate's automatic session context management -->
    <property name="current_session_context_class">thread</property>
    <!-- Disable the second-level cache -->
    <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
    <!-- Echo all executed SQL to stdout -->
    <property name="show_sql">true</property>
    <!-- Drop and re-create the database schema on startup -->
    <property name="hbm2ddl.auto">update</property>

    <mapping class="test.hibernate.Student" />
    <mapping class="test.hibernate.College" />
</session-factory>

【问题讨论】:

  • @All:没有人告诉我,Main.java 中的完全代码错位:(
  • 问题可能是列表对象的创建
  • [eons later] 在我的 Spring Boot 应用程序中,@Access(AccessType.FIELD)(在我的情况下我想使用 FIELD)是唯一解决它的人

标签: java hibernate orm


【解决方案1】:

您正在使用字段访问策略(由@Id 注释确定)。将任何与 JPA 相关的注释放在每个字段的正上方,而不是 getter 属性

@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)
private List<Student> students;

【讨论】:

  • @Arthur Ronald F D Garcia:谢谢,效果很好。但是,该程序现在被新的程序停止了。 object references an unsaved transient instance - save the transient instance before flushing你知道这个错误吗。如果不是就离开它。我正在寻找。
  • @Arthur Ronald F D Garcia:你好,我看到了我当前错误的解决方案,我在之前的评论中问过这个问题。这是链接。 stackoverflow.com/questions/1667177/… 解决方案包括cascade=CascadeType.ALL。但对我来说,它在我的日食中显示错误并且没有任何建议。你知道吗? :)
  • @Arthur +1 Good catch @MaRaVan 您可以使用字段访问策略或属性访问策略,但您必须在类层次结构中保持一致,您不能混合策略,至少不能在JPA 1.0。虽然 JPA 2.0 使混合策略成为可能,但您需要额外的注释(因此更复杂)。因此,建议选择一种策略并在您的应用程序中坚持使用它。见2.2.2.2. Access type
  • @Arthur Ronald F D Garcia:嗯……我已经添加了persistence.cascade 现在它已清除。但我再次收到旧错误object references an unsaved transient instance - save the transient instance before flushing任何建议!!! :+|
  • @All:没有人告诉我,Main.java 中的完全代码错位:(
【解决方案2】:

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

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

【讨论】:

  • + targetClass不是必需的,因为您提到了列表的类型&lt;Integer&gt;
  • 这似乎是必要的,因为我正在寻找解决这个问题的方法,并将 @ElementCollection(targetClass=String.class) 添加到我的简单字符串列表中解决了它。
  • 你可以使用 Set 代替 List,它应该可以正常工作。
【解决方案3】:

访问策略问题

作为 JPA 提供者,Hibernate 可以自省这两个实体属性 (实例字段)或访问器(实例属性)。默认, @Id 注释的位置提供了默认访问权限 战略。当放置在一个字段上时,Hibernate 将假定基于字段 使用权。放置在标识符 getter 上,Hibernate 将使用 基于属性的访问。

基于字段的访问

当使用基于字段的访问时,添加其他实体级方法更加灵活,因为 Hibernate 不会考虑持久状态的那些部分

@Entity
public class Simple {

@Id
private Integer id;

@OneToMany(targetEntity=Student.class, mappedBy="college", 
fetch=FetchType.EAGER)
private List<Student> students;

//getter +setter
}

基于属性的访问

当使用基于属性的访问时,Hibernate 使用访问器来读取和写入实体状态

@Entity
public class Simple {

private Integer id;
private List<Student> students;

@Id
public Integer getId() {
    return id;
}

public void setId( Integer id ) {
    this.id = id;
}
@OneToMany(targetEntity=Student.class, mappedBy="college", 
fetch=FetchType.EAGER)
public List<Student> getStudents() {
   return students;
}
public void setStudents(List<Student> students) {
    this.students = students;
}

}

但您不能同时使用基于字段和基于属性的访问。它会为您显示类似的错误

更多想法请关注this

【讨论】:

    【解决方案4】:
    @Access(AccessType.PROPERTY)
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name="userId")
    public User getUser() {
        return user;
    }
    

    我有同样的问题,我通过添加@Access(AccessType.PROPERTY)解决了它

    【讨论】:

    • 在我的 Spring Boot 应用程序中,@Access(AccessType.FIELD)(在我的情况下我想使用 FIELD)是唯一解决它的方法
    【解决方案5】:

    只需在数组列表变量上插入@ElementCollection 注释,如下所示:

    @ElementCollection
    private List<Price> prices = new ArrayList<Price>();
    

    希望对你有帮助

    【讨论】:

    • 太好了!它就像一个魅力!其他答案对我不起作用。这真的做到了。主要答案只是让我陷入了更多我必须与这个问题分开解决的问题。好答案!
    【解决方案6】:

    在我的情况下,缺少@OneToOne 注释是愚蠢的,我在没有它的情况下设置了@MapsId

    【讨论】:

      【解决方案7】:

      虽然我是 hibernate 新手,但几乎没有研究(我们可以说是反复试验) 我发现这是由于注释方法/文件不一致造成的。

      当您在变量上注释@ID 时,请确保所有其他注释也仅在变量上完成 并且当您在 getter 方法上对其进行注释时,请确保您仅注释所有其他 getter 方法而不是它们各自的变量。

      【讨论】:

        【解决方案8】:

        别担心!由于注释而出现此问题。而不是基于字段的访问,基于属性的访问解决了这个问题。代码如下:

        package onetomanymapping;
        
        import java.util.List;
        
        import javax.persistence.*;
        
        @Entity
        public class College {
        private int collegeId;
        private String collegeName;
        private List<Student> students;
        
        @OneToMany(targetEntity = Student.class, mappedBy = "college", 
            cascade = CascadeType.ALL, fetch = FetchType.EAGER)
        public List<Student> getStudents() {
            return students;
        }
        
        public void setStudents(List<Student> students) {
            this.students = students;
        }
        
        @Id
        @GeneratedValue
        public int getCollegeId() {
            return collegeId;
        }
        
        public void setCollegeId(int collegeId) {
            this.collegeId = collegeId;
        }
        
        public String getCollegeName() {
            return collegeName;
        }
        
        public void setCollegeName(String collegeName) {
            this.collegeName = collegeName;
        }
        

        }

        【讨论】:

          【解决方案9】:

          以防其他人在这里遇到与我遇到的相同问题。我遇到了与上面相同的错误:

          init 方法调用失败;嵌套异常是 org.hibernate.MappingException:无法确定类型: java.util.Collection,在桌子上:

          Hibernate 使用反射来确定实体中的哪些列。我有一个以“get”开头的私有方法,并返回一个也是休眠实体的对象。即使是您希望 hibernate 忽略的私有 getter,也必须使用 @Transient 进行注释。一旦我添加了@Transient 注释,一切就正常了。

          @Transient 
          private List<AHibernateEntity> getHibernateEntities() {
             ....
          }
          

          【讨论】:

            【解决方案10】:

            将模式名称添加到实体中,它会找到它。为我工作!

            【讨论】:

              【解决方案11】:

              列出的解决方案都不适合我,原因如下:我将实体继承与属性访问策略结合使用。

              @Entity(name = "spec")
              @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
              @DiscriminatorFormula(value = "type")
              public abstract class Spec extends BasicEntity { ... }
              

              两个继承者都有一个超类中没有的属性。其中一个继承者具有JoinColumnOneToOne 注释以整合Basic 属性类型的使用(实际上,如果没有带有JoinColumn 注释的适当getter,则Intellij IDEA 会突出显示该字段。

              @Data
              @Entity
              @DiscriminatorValue("data")
              public class DataSpec extends Spec {
              
                  private Payload payload;
              
                  @OneToOne
                  @NotFound(action = NotFoundAction.IGNORE)
                  @JoinColumn(name = "payload_id")
                  public Payload getPayload() {
                      return payload;
                  }
              

              但是,第二个继承者没有针对这个新属性的任何注释,并且不知何故,IDEA 没有突出显示它来警告我这个问题!

              @Data
              @Entity
              @DiscriminatorValue("blob")
              public class BlobSpec extends Spec {
              
                  private Payload payload;
                //^^^^^^^^^^^^^^^^^^^^^^^^ No getter with @JoinColumn! Should be highlighted with static code check!
              

              我只能通过调试休眠类来对问题进行分类。我发现我的实体在MetadataImpl.validate 方法中没有通过验证。例外没有告诉你。它只打印spec 表中发生的错误,不是详细消息。

              【讨论】:

                【解决方案12】:

                删除

                ma​​ppedBy="college" 在@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)

                这解决了我的问题。 ;)

                【讨论】:

                  【解决方案13】:

                  遇到同样的问题,我的问题是我没有在 id 字段上指定@Id 注释。

                  当我注释它时,一切都很顺利。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2020-01-23
                    • 2016-06-05
                    • 2016-08-28
                    • 1970-01-01
                    • 2013-03-28
                    • 1970-01-01
                    • 2016-10-04
                    • 2016-06-23
                    相关资源
                    最近更新 更多