org.hibernate.MappingException: No se pudo determinar el tipo para: java.util.List, en la tabla: College, para las columnas: [org.hibernate.mapping.Column (estudiantes)]

96

Estoy usando Hibernate para todas las operaciones CRUD en mi proyecto. No funciona para las relaciones uno a varios y varios a uno. Me da el siguiente error.

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

Luego, de nuevo, revisé este video tutorial . Para mí es muy simple, al principio. Pero no puedo hacer que funcione. También ahora dice

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

He realizado algunas búsquedas en Internet, alguien dice que es un error en Hibernate , y algunos dicen que al agregar @GenereatedValue, este error se borrará, pero no funciona para mí.

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


}

Consola:

 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)

El 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
fuente
1
@All: Nadie me contó sobre la ubicación incorrecta del código en Main.java :(
el problema puede ser la creación de un objeto de lista
Kemal Duran
1
[eones después] en mi aplicación de arranque de primavera, @Access(AccessType.FIELD)(en mi caso quería ir con FIELD) fue el único que lo resolvió
Scaramouche

Respuestas:

169

Está utilizando una estrategia de acceso al campo (determinada por la anotación @Id). Coloque cualquier anotación relacionada con JPA justo encima de cada campo en lugar de la propiedad getter

@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)
private List<Student> students;
Arthur Ronald
fuente
@Arthur Ronald FD García: Gracias, funcionó muy bien. Pero, el programa ahora es detenido por uno nuevo. object references an unsaved transient instance - save the transient instance before flushing¿Conoce este error? Si no, déjalo. Estoy buscando.
@Arthur Ronald FD García: Hola de nuevo, vi una solución para mi error actual, que pregunté en mi comentario anterior. Este es el enlace. stackoverflow.com/questions/1667177/… La solución incluye cascade=CascadeType.ALL. Pero para mí, muestra un error y no hay sugerencias en mi eclipse. ¿Sabes algo sobre eso? :)
9
@Arthur +1 Buena captura @MaRaVan Puede usar la estrategia de acceso al campo o la estrategia de acceso a la propiedad, pero debe ser coherente dentro de una jerarquía de clases, no puede mezclar las estrategias, al menos no en JPA 1.0. Sin embargo, JPA 2.0 hace posible mezclar estrategias, pero necesitaría anotaciones adicionales (y por lo tanto más complejidad). Así que la recomendación es elegir una estrategia y ceñirse a ella en su aplicación. Ver 2.2.2.2. Tipo de acceso .
Pascal Thivent
@Arthur Ronald FD García: Hmmmm ... He agregado persistence.cascadeAhora está despejado. Pero de nuevo recibo el antiguo error object references an unsaved transient instance - save the transient instance before flushingAnY Suggestions !!! : + |
@All: Nadie me contó sobre la ubicación incorrecta del código en Main.java :(
78

Agregar el @ElementCollectioncampo a la lista resolvió este problema:

    @Column
    @ElementCollection(targetClass=Integer.class)
    private List<Integer> countries;
Biggy_java2
fuente
5
+ targetClassno es necesario ya que mencionaste el tipo de lista<Integer>
O.Badr
1
Parece ser necesario, porque estaba buscando una solución para este problema exactamente, y agregando @ElementCollection (targetClass = String.class) a mi lista simple de cadenas lo resolvió.
Angel O'Sphere
32

Problema con las estrategias de acceso

Como proveedor de JPA, Hibernate puede introspectar tanto los atributos de entidad (campos de instancia) como los accesores (propiedades de instancia). De forma predeterminada, la ubicación de la @Idanotación proporciona la estrategia de acceso predeterminada. Cuando se coloca en un campo, Hibernate asumirá el acceso basado en el campo. Colocado en el captador de identificador, Hibernate utilizará el acceso basado en propiedades.

Acceso basado en campo

Cuando se usa el acceso basado en campo, agregar otros métodos a nivel de entidad es mucho más flexible porque Hibernate no considerará esos como parte del estado de persistencia

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

Acceso basado en propiedad

Cuando se usa el acceso basado en propiedades, Hibernate usa los accesos para leer y escribir el estado de la entidad

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

}

Pero no puede usar el acceso basado en campos y en propiedades al mismo tiempo. Se mostrará como ese error para ti

Para más idea sigue esto

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

Tengo los mismos problemas, lo resolví agregando @Access(AccessType.PROPERTY)

usuario2406031
fuente
en mi aplicación de arranque de primavera, @Access(AccessType.FIELD)(en mi caso, quería ir con FIELD) fue el único que lo resolvió
Scaramouche
2

¡No se preocupe! Este problema se produce debido a la anotación. En lugar del acceso basado en el campo, el acceso basado en la propiedad resuelve este problema. El código de la siguiente manera:

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 piedra
fuente
2

Simplemente inserte la anotación @ElementCollection sobre su variable de lista de matriz, como se muestra a continuación:

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

espero que esto ayude

Renato Vasconcellos
fuente
¡Eso es genial! ¡Funcionó a las mil maravillas! Las otras respuestas no me funcionan. Esto realmente lo hizo. La respuesta principal me metió en más problemas que tuve que abordar por separado de este. ¡Buena respuesta!
Compilador v2
2

En mi caso, fue una estupidez faltar la anotación @OneToOne, configuré @MapsId sin ella

S. Dayneko
fuente
1

Aunque soy nuevo en hibernar pero con poca investigación (ensayo y error, podemos decir) descubrí que se debe a una inconsistencia en la anotación de métodos / archivos.

cuando esté anotando @ID en la variable, asegúrese de que todas las demás anotaciones también se realicen solo en la variable y cuando lo esté anotando en el método getter, asegúrese de anotar todos los demás métodos getter solo y no sus respectivas variables.

ShailendraChoudhary
fuente
1

En caso de que alguien más aterrice aquí con el mismo problema que encontré. Recibía el mismo error que el anterior:

Error al invocar el método init; La excepción anidada es org.hibernate.MappingException: No se pudo determinar el tipo para: java.util.Collection, en la tabla:

Hibernate usa la reflexión para determinar qué columnas están en una entidad. Tenía un método privado que comenzaba con 'get' y devolvía un objeto que también era una entidad de hibernación. Incluso los captadores privados que desea que hibernate ignore deben anotarse con @Transient. Una vez que agregué la anotación @Transient, todo funcionó.

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