org.hibernate.MappingException: не удалось определить тип для: java.util.List, в таблице: Колледж, для столбцов: [org.hibernate.mapping.Column (студенты)]

97

Я использую Hibernate для всех операций CRUD в моем проекте. Это не работает для отношений «один-ко-многим» и «многие-к-одному». Это дает мне ошибку ниже.

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

Затем я снова просмотрел этот видеоурок . Вначале для меня это очень просто. Но я не могу заставить его работать. Также сейчас, говорит

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

Я провел несколько поисков в Интернете, там кто-то сообщил об ошибке в 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>

Карл Рихтер
источник
1
@All: Мне никто не сказал, полное смещение кода в Main.java :(
проблема может заключаться в создании объекта списка
Кемаль Дуран
1
[эоны спустя] в моем приложении весенней загрузки @Access(AccessType.FIELD)(в моем случае я хотел использовать FIELD) было единственное, что решило эту проблему
Scaramouche

Ответы:

176

Вы используете стратегию доступа к полю (определяется аннотацией @Id). Поместите любую аннотацию, связанную с JPA, прямо над каждым полем вместо свойства getter

@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)
private List<Student> students;
Артур Рональд
источник
@Arthur Ronald FD Garcia: Спасибо, отлично сработало. Но теперь программа остановлена ​​новой. object references an unsaved transient instance - save the transient instance before flushingВы знаете об этой ошибке. Если не просто оставь это. Я ищу.
@Arthur Ronald FD Garcia: Привет снова, я увидел решение моей текущей ошибки, о котором я спросил в моем предыдущем комментарии. Это ссылка. stackoverflow.com/questions/1667177/… Решение включает cascade=CascadeType.ALL. Но для меня это показывает ошибку и никаких предложений в моем затмении. Вы что-нибудь знаете об этом. :)
10
@Arthur +1 Хороший улов @MaRaVan Вы можете использовать либо стратегию доступа к полю, либо стратегию доступа к собственности, но вы должны быть последовательны в иерархии классов, вы не можете смешивать стратегии, по крайней мере, не в JPA 1.0. JPA 2.0 позволяет смешивать стратегии, но вам потребуются дополнительные аннотации (и, следовательно, большая сложность). Поэтому рекомендуется выбрать одну стратегию и придерживаться ее в своем приложении. См. 2.2.2.2. Тип доступа .
Паскаль Тивент,
@Arthur Ronald FD Garcia: Хммм ... Я добавил. persistence.cascadeТеперь все очищено. Но я снова получаю старую ошибку object references an unsaved transient instance - save the transient instance before flushingЛюбые предложения !!! : + |
@All: Мне никто не сказал, полное смещение кода в Main.java :(
79

Добавление @ElementCollectionполя в список решило эту проблему:

    @Column
    @ElementCollection(targetClass=Integer.class)
    private List<Integer> countries;
Biggy_java2
источник
5
+ targetClassне обязательно, так как вы упомянули тип списка<Integer>
О.Бадр 03
1
Это кажется необходимым, потому что я искал решение именно для этой проблемы, и добавление @ElementCollection (targetClass = String.class) в мой простой список строк решило это.
Angel O'Sphere
33

Проблема со стратегиями доступа

Как поставщик JPA, Hibernate может анализировать как атрибуты сущности (поля экземпляра), так и средства доступа (свойства экземпляра). По умолчанию размещение @Idаннотации дает стратегию доступа по умолчанию. При размещении в поле Hibernate предполагает доступ на основе поля. Помещенный в получатель идентификатора, 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;
}

}

Но вы не можете использовать доступ как на основе полей, так и на основе свойств одновременно. Это покажет вам эту ошибку

Для получения дополнительной информации следуйте этому

JustCode
источник
9
@Access(AccessType.PROPERTY)
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="userId")
public User getUser() {
    return user;
}

У меня такие же проблемы, решил добавлением @Access(AccessType.PROPERTY)

user2406031
источник
в моем весеннем загрузочном приложении @Access(AccessType.FIELD)(в моем случае я хотел пойти с FIELD) было единственное, что решило эту проблему
Scaramouche
2

Не волнуйтесь! Эта проблема возникает из-за аннотации. Вместо доступа на основе поля эту проблему решает доступ на основе свойств. Код следующий:

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

}

Аарон Стоун
источник
2

Просто вставьте аннотацию @ElementCollection поверх переменной списка массивов, как показано ниже:

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

надеюсь, это поможет

Ренато Васконселлос
источник
Замечательно! Оно работало завораживающе! Другие ответы мне не подходят. Это действительно сработало. Основной ответ заставил меня столкнуться с большим количеством проблем, которые мне пришлось решать отдельно от этой. Хороший ответ!
Компилятор v2
1

Хотя я новичок в спящем режиме, но с небольшим исследованием (можно сказать, методом проб и ошибок) я обнаружил, что это связано с несогласованностью в аннотировании методов / полей.

когда вы аннотируете @ID для переменной, убедитесь, что все другие аннотации также сделаны только для переменной, и когда вы аннотируете ее в методе получения, убедитесь, что вы аннотируете только все другие методы получения, а не их соответствующие переменные.

Шайлендра
источник
1

На случай, если кто-то еще попадет сюда с той же проблемой, с которой я столкнулся. Я получал ту же ошибку, что и выше:

Не удалось вызвать метод инициализации; вложенное исключение - org.hibernate.MappingException: не удалось определить тип для: java.util.Collection в таблице:

Hibernate использует отражение, чтобы определить, какие столбцы находятся в сущности. У меня был частный метод, который начинался с get и возвращал объект, который также был объектом гибернации. Даже частные геттеры, которые вы хотите, чтобы hibernate игнорировал, должны быть аннотированы @Transient. Как только я добавил аннотацию @Transient, все заработало.

@Transient 
private List<AHibernateEntity> getHibernateEntities() {
   ....
}
jbppsu
источник
1

В моем случае было глупо пропустить аннотацию @OneToOne, я установил @MapsId без нее

С.Дайнеко
источник