org.hibernate.MappingException: Typ für: java.util.List in Tabelle: College für Spalten konnte nicht ermittelt werden: [org.hibernate.mapping.Column (Studenten)]

93

Ich verwende Hibernate für alle CRUD-Operationen in meinem Projekt. Es funktioniert nicht für Eins-zu-Viele- und Viele-zu-Eins-Beziehungen. Es gibt mir den folgenden Fehler.

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

Andererseits habe ich dieses Video-Tutorial durchgesehen . Am Anfang ist es für mich sehr einfach. Aber ich kann es nicht zum Laufen bringen. Es auch jetzt, sagt

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

Ich habe einige Suchanfragen im Internet durchgeführt, dort hat jemand einen Fehler im Ruhezustand gemeldet , und einige sagen, durch Hinzufügen von @GenereatedValue wird dieser Fehler behoben , aber er funktioniert bei mir nicht.

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


}

Konsole:

 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)

Das 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>

Karl Richter
quelle
1
@All: Niemand hat mir davon erzählt, dass der Code in Main.java völlig falsch platziert wurde :(
Das Problem kann die Erstellung eines Listenobjekts sein
Kemal Duran
1
[Äonen später] in meiner Spring Boot App @Access(AccessType.FIELD)(in meinem Fall wollte ich mit FIELD gehen) war die einzige, die es löste
Scaramouche

Antworten:

167

Sie verwenden Feld Zugriffsstrategie (durch @Id Anmerkung bestimmt). Platzieren Sie alle JPA-bezogenen Anmerkungen direkt über jedem Feld anstelle der Getter-Eigenschaft

@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)
private List<Student> students;
Arthur Ronald
quelle
@ Arthur Ronald FD Garcia: Danke, es hat super funktioniert. Das Programm wird jetzt jedoch durch ein neues Programm gestoppt. object references an unsaved transient instance - save the transient instance before flushingKennen Sie diesen Fehler? Wenn nicht, lass es einfach. Ich suche.
@ Arthur Ronald FD Garcia: Hallo nochmal, ich habe eine Lösung für meinen aktuellen Fehler gesehen, die ich in meinem vorherigen Kommentar gefragt habe. Das ist die Verbindung. stackoverflow.com/questions/1667177/… Die Lösung umfasst cascade=CascadeType.ALL. Aber für mich zeigt es Fehler und keine Vorschläge in meiner Sonnenfinsternis. Weißt du etwas darüber? :)
9
@Arthur +1 Guter Fang @MaRaVan Sie können entweder eine Feldzugriffsstrategie oder eine Eigenschaftszugriffsstrategie verwenden, müssen jedoch innerhalb einer Klassenhierarchie konsistent sein. Sie können die Strategien nicht mischen, zumindest nicht in JPA 1.0. JPA 2.0 ermöglicht zwar das Mischen von Strategien, Sie benötigen jedoch zusätzliche Anmerkungen (und damit mehr Komplexität). Die Empfehlung lautet daher, eine Strategie auszuwählen und diese in Ihrer Anwendung beizubehalten. Siehe 2.2.2.2. Zugriffstyp .
Pascal Thivent
@ Arthur Ronald FD Garcia: Hmmmm ... ich habe hinzugefügt persistence.cascadeJetzt ist es geklärt. Aber ich bekomme wieder den alten Fehler object references an unsaved transient instance - save the transient instance before flushingJEDE Vorschläge !!! : + |
@ All: Niemand hat mir von der völligen Code-Fehlplatzierung in Main.java erzählt :(
76

Durch Hinzufügen des @ElementCollectionFelds zur Liste wurde dieses Problem behoben:

    @Column
    @ElementCollection(targetClass=Integer.class)
    private List<Integer> countries;
Biggy_java2
quelle
5
+ targetClassist nicht notwendig, da Sie den Typ der Liste erwähnt haben<Integer>
O.Badr
1
Dies scheint notwendig zu sein, da ich nach einer Lösung für genau dieses Problem gesucht und @ElementCollection (targetClass = String.class) zu meiner einfachen Liste von gelösten Zeichenfolgen hinzugefügt habe.
Angel O'Sphere
32

Problem mit Zugriffsstrategien

Als JPA-Anbieter kann Hibernate sowohl die Entitätsattribute (Instanzfelder) als auch die Accessoren (Instanzeigenschaften) überprüfen. Standardmäßig gibt die Platzierung der @IdAnmerkung die Standardzugriffsstrategie an. Wenn der Ruhezustand auf einem Feld platziert wird, übernimmt er den feldbasierten Zugriff. Hibernate wird auf dem Identifier Getter platziert und verwendet den eigenschaftsbasierten Zugriff.

Feldbasierter Zugriff

Bei Verwendung des feldbasierten Zugriffs ist das Hinzufügen anderer Methoden auf Entitätsebene viel flexibler, da im Ruhezustand diese Teile des Persistenzstatus nicht berücksichtigt werden

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

Eigenschaftsbasierter Zugriff

Bei Verwendung des eigenschaftsbasierten Zugriffs verwendet Hibernate die Accessoren zum Lesen und Schreiben des Entitätsstatus

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

}

Sie können jedoch nicht gleichzeitig den feldbasierten und den eigenschaftsbasierten Zugriff verwenden. Es wird für Sie so ein Fehler angezeigt

Für weitere Ideen folgen Sie diesem

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

Ich habe die gleichen Probleme, ich habe es durch Hinzufügen gelöst @Access(AccessType.PROPERTY)

user2406031
quelle
in meiner Spring Boot App @Access(AccessType.FIELD)(in meinem Fall wollte ich mit FIELD gehen) war die einzige, die es löste
Scaramouche
2

Mach dir keine Sorgen! Dieses Problem tritt aufgrund der Anmerkung auf. Anstelle eines feldbasierten Zugriffs löst der eigenschaftsbasierte Zugriff dieses Problem. Der Code lautet wie folgt:

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

}}

Aaron Stein
quelle
2

Fügen Sie einfach die Annotation @ElementCollection wie folgt über Ihre Array-Listenvariable ein:

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

ich hoffe das hilft

Renato Vasconcellos
quelle
Das ist großartig! Es hat wie ein Zauber funktioniert! Die anderen Antworten funktionieren bei mir nicht. Das hat es wirklich geschafft. Die Hauptantwort brachte mich nur in weitere Probleme, die ich separat von diesem ansprechen musste. Gute Antwort!
Compiler v2
2

In meinem Fall war es dumm, die @ OneToOne-Annotation zu vermissen, ich habe @MapsId ohne sie gesetzt

S.Dayneko
quelle
1

Obwohl ich neu im Winterschlaf bin, habe ich mit wenig Forschung (Versuch und Irrtum können wir sagen) herausgefunden, dass dies auf Inkonsistenzen bei der Annotation der Methoden / Dateien zurückzuführen ist.

Wenn Sie @ID für eine Variable mit Anmerkungen versehen, stellen Sie sicher, dass alle anderen Anmerkungen auch nur für Variablen ausgeführt werden. Wenn Sie sie für die Getter-Methode mit Anmerkungen versehen, stellen Sie sicher, dass Sie nur alle anderen Getter-Methoden und nicht ihre jeweiligen Variablen mit Anmerkungen versehen.

ShailendraChoudhary
quelle
1

Für den Fall, dass jemand anderes mit dem gleichen Problem hier landet, auf das ich gestoßen bin. Ich habe den gleichen Fehler wie oben erhalten:

Aufruf der init-Methode fehlgeschlagen; verschachtelte Ausnahme ist org.hibernate.MappingException: Typ für: java.util.Collection in Tabelle:

Der Ruhezustand verwendet die Reflexion, um zu bestimmen, welche Spalten sich in einer Entität befinden. Ich hatte eine private Methode, die mit 'get' begann und ein Objekt zurückgab, das auch eine Entität im Ruhezustand war. Sogar private Getter, die im Ruhezustand ignoriert werden sollen, müssen mit @Transient kommentiert werden. Nachdem ich die Annotation @Transient hinzugefügt hatte, funktionierte alles.

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