org.hibernate.MappingException: impossibile determinare il tipo per: java.util.List, nella tabella: College, per le colonne: [org.hibernate.mapping.Column (students)]


96

Sto usando Hibernate per tutte le operazioni CRUD nel mio progetto. Non funziona per le relazioni uno-a-molti e molti-a-uno. Mi dà il seguente errore.

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

Poi di nuovo ho seguito questo video tutorial . Per me è molto semplice, all'inizio. Ma non riesco a farlo funzionare. Anche adesso, dice

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

Ho eseguito alcune ricerche su Internet, qualcuno dice che è un bug in Hibernate e alcuni dicono che, aggiungendo @GenereatedValue, questo errore verrà cancellato, ma non funziona per me.

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


}

Console:

 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)

L'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
@Tutti: nessuno mi ha parlato del totale smarrimento del codice in Main.java :(

il problema può essere la creazione dell'oggetto elenco
Kemal Duran

1
[eoni dopo] nella mia app di avvio primaverile, @Access(AccessType.FIELD)(nel mio caso volevo usare FIELD) era l'unico che lo ha risolto
Scaramouche

Risposte:


169

Stai utilizzando la strategia di accesso al campo (determinata dall'annotazione @Id). Metti qualsiasi annotazione correlata a JPA proprio sopra ogni campo invece della proprietà getter

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

@ Arthur Ronald FD Garcia: Grazie, ha funzionato benissimo. Ma il programma è ora interrotto da uno nuovo. object references an unsaved transient instance - save the transient instance before flushingSei a conoscenza di questo errore. Se non lo lasci e basta. Sto cercando.

@ Arthur Ronald FD Garcia: Ciao di nuovo, ho visto la soluzione per il mio errore attuale, che ho chiesto nel mio commento precedente. Questo è il collegamento. stackoverflow.com/questions/1667177/… La soluzione include cascade=CascadeType.ALL. Ma per me mostra errori e nessun suggerimento nella mia eclissi. Ne sai qualcosa. :)

9
@Arthur +1 Buona presa @MaRaVan Puoi usare sia la strategia di accesso al campo che la strategia di accesso alla proprietà ma devi essere coerente all'interno di una gerarchia di classi, non puoi mescolare le strategie, almeno non in JPA 1.0. Tuttavia, JPA 2.0 rende possibile combinare strategie, ma avresti bisogno di annotazioni extra (e quindi più complessità). Quindi il consiglio è di scegliere una strategia e di rispettarla nella tua applicazione. Vedere 2.2.2.2. Tipo di accesso .
Pascal Thivent

@ Arthur Ronald FD Garcia: Hmmmm ... ho aggiunto persistence.cascadeOra è stato cancellato. Ma ottengo di nuovo il vecchio errore object references an unsaved transient instance - save the transient instance before flushingTutti i suggerimenti !!! : + |

@Tutti: Nessuno mi ha parlato del totale smarrimento del codice in Main.java :(

78

L'aggiunta del @ElementCollectioncampo all'elenco ha risolto questo problema:

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

5
+ targetClassnon è necessario in quanto hai menzionato il tipo di lista<Integer>
O.Badr

1
Sembra essere necessario, perché stavo cercando una soluzione esattamente per questo problema e l'aggiunta di @ElementCollection (targetClass = String.class) al mio semplice elenco di stringhe lo ha risolto.
Angel O'Sphere

32

Problema con le strategie di accesso

In qualità di provider JPA, Hibernate può analizzare sia gli attributi dell'entità (campi dell'istanza) che le funzioni di accesso (proprietà dell'istanza). Per impostazione predefinita, il posizionamento @Iddell'annotazione fornisce la strategia di accesso predefinita. Quando viene posizionato su un campo, Hibernate presume l'accesso basato sul campo. Posizionato sul getter dell'identificatore, Hibernate utilizzerà l'accesso basato sulla proprietà.

Accesso basato sul campo

Quando si utilizza l'accesso basato sul campo, l'aggiunta di altri metodi a livello di entità è molto più flessibile perché Hibernate non considera quelle parti dello stato di persistenza

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

Accesso basato sulla proprietà

Quando si utilizza l'accesso basato sulla proprietà, Hibernate utilizza le funzioni di accesso sia per leggere che per scrivere lo stato dell'entità

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

}

Ma non puoi utilizzare contemporaneamente l'accesso basato sul campo e quello basato sulla proprietà. Mostrerà questo errore per te

Per ulteriori idee segui questo


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

Ho gli stessi problemi, l'ho risolto aggiungendo @Access(AccessType.PROPERTY)


nella mia app di avvio primaverile, @Access(AccessType.FIELD)(nel mio caso volevo usare FIELD) era l'unico che lo ha risolto
Scaramouche

2

Non preoccuparti! Questo problema si verifica a causa dell'annotazione. Invece dell'accesso basato sul campo, l'accesso basato sulla proprietà risolve questo problema. Il codice come segue:

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

Basta inserire l'annotazione @ElementCollection sulla variabile dell'elenco di array, come di seguito:

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

Spero che aiuti


È fantastico! Ha funzionato come un fascino! Le altre risposte non funzionano per me. Questo lo ha fatto davvero. La risposta principale mi ha appena messo in più problemi che ho dovuto affrontare separatamente da questo. Buona risposta!
Compilatore v2

2

Nel mio caso è stato stupido che mancava l'annotazione @OneToOne, ho impostato @MapsId senza di essa


1

Sebbene io sia nuovo per l'ibernazione ma con poche ricerche (tentativi ed errori possiamo dire) ho scoperto che è dovuto a incoerenze nell'annotazione dei metodi / campi.

quando stai annotando @ID sulla variabile assicurati che anche tutte le altre annotazioni siano fatte solo sulla variabile e quando la stai annotando sullo stesso metodo getter assicurati di annotare solo tutti gli altri metodi getter e non le rispettive variabili.


1

Nel caso qualcun altro arrivi qui con lo stesso problema che ho riscontrato. Ho ricevuto lo stesso errore di cui sopra:

Invocazione del metodo init non riuscita; l'eccezione annidata è org.hibernate.MappingException: impossibile determinare il tipo per: java.util.Collection, nella tabella:

Hibernate utilizza la riflessione per determinare quali colonne si trovano in un'entità. Avevo un metodo privato che iniziava con "get" e restituiva un oggetto che era anche un'entità di ibernazione. Anche i getter privati ​​che vuoi che l'ibernazione ignori devono essere annotati con @Transient. Dopo aver aggiunto l'annotazione @Transient, tutto ha funzionato.

@Transient 
private List<AHibernateEntity> getHibernateEntities() {
   ....
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.