org.hibernate.MappingException: Не вдалося визначити тип для: java.util.List, у таблиці: College, для стовпців: [org.hibernate.mapping.Column (студенти)]


96

Я використовую 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)]

Я провів кілька пошуків в Інтернеті, там хтось повідомляє про свою помилку в режимі глибокого сну , а деякі кажуть, додавши @GenereatedValue, ця помилка буде видалена , але це не працює для мене.

Коледж.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

Студент.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
[eons пізніше] у моєму весняному завантажувальному додатку, @Access(AccessType.FIELD)(у моєму випадку я хотів піти з FIELD) був єдиним, хто вирішив це
Scaramouche

Відповіді:


168

Ви використовуєте стратегію доступу до полів (визначається анотацією @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. Але для мене це показує помилку та відсутність пропозицій у моєму затемненні. Чи знаєте ви щось про це. :)

9
@Arthur +1 Хороший улов @MaRaVan Ви можете використовувати або стратегію доступу до поля, або стратегію доступу до власності, але ви повинні бути послідовними в ієрархії класів, ви не можете змішувати стратегії, принаймні не в JPA 1.0. JPA 2.0 дозволяє поєднувати стратегії, однак вам потрібні додаткові анотації (і, отже, більша складність). Тож рекомендація полягає у тому, щоб вибрати одну стратегію та дотримуватися її у своїй заявці. Див. 2.2.2.2. Тип доступу .
Pascal Thivent

@Arthur Ronald FD Garcia: Хм-м-м-м ... Я додав, що persistence.cascadeтепер це очищено. Але я знову отримую стару помилкуobject references an unsaved transient instance - save the transient instance before flushing будь-які пропозиції !!! : + |

@ All: Ніхто мені не розповідав про неповноцінне розміщення коду в Main.java :(

78

Додавання поля @ElementCollectionдо списку вирішило цю проблему:

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

5
+ targetClassне є необхідним, оскільки ви згадали тип списку<Integer>
О.Бадр,

1
Це здається необхідним, оскільки я шукав рішення саме для цієї проблеми, і додавши @ElementCollection (targetClass = String.class) до свого простого списку рядків це вирішило.
Angel O'Sphere

32

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

Як постачальник 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;
}

}

Але ви не можете одночасно використовувати як польовий, так і власний доступ. Це буде відображатися як ця помилка для вас

Щоб отримати більше ідей, дотримуйтесь цього


9
@Access(AccessType.PROPERTY)
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="userId")
public User getUser() {
    return user;
}

У мене такі ж проблеми, я вирішив це за допомогою add @Access(AccessType.PROPERTY)


у моєму весняному завантажувальному додатку, @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>();

Сподіваюся, це допоможе


Це чудово! Це спрацювало як шарм! Інші відповіді для мене не працюють. Це справді це зробило. Основна відповідь просто завела мене до більшої кількості проблем, які мені довелося вирішувати окремо від цієї. Хороша відповідь!
Compiler v2

2

У моєму випадку дурно не вистачало анотації @OneToOne, я встановив @MapsId без неї


1

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

коли ви анотуєте @ID для змінної, переконайтеся, що всі інші анотації також виконуються лише для змінної, а коли ви анотуєте її за методом getter, переконайтеся, що ви анотуєте лише всі інші методи getter, а не їх відповідні змінні.


1

На випадок, якщо хтось інший приземлиться сюди з тією ж проблемою, з якою я зіткнувся. Я отримував ту ж помилку, що і вище:

Не вдалося викликати метод init; вкладеним винятком є ​​org.hibernate.MappingException: Не вдалося визначити тип для: java.util.Collection, у таблиці:

Hibernate використовує відображення, щоб визначити, які стовпці є в сутності. У мене був приватний метод, який починався з 'get' і повертав об'єкт, який також був сплячим режимом. Навіть приватні геттери, які ви хочете ігнорувати в сплячому режимі, повинні бути анотовані @Transient. Як тільки я додав анотацію @Transient, все запрацювало.

@Transient 
private List<AHibernateEntity> getHibernateEntities() {
   ....
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.