org.hibernate.MappingException: Não foi possível determinar o tipo para: java.util.List, na tabela: College, para colunas: [org.hibernate.mapping.Column (alunos)]


96

Estou usando o Hibernate para todas as operações CRUD em meu projeto. Não funciona para relacionamentos Um-para-Muitos e Muitos-para-Um. Isso me dá o erro abaixo.

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

Então, novamente, passei por este tutorial em vídeo . É muito simples para mim, no começo. Mas, eu não consigo fazer funcionar. Também agora, diz

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

Já fiz algumas buscas na internet, tem alguém falando que é um bug no Hibernate , e alguns dizem que adicionando @GenereatedValue esse erro vai ser apagado, mas não funciona pra mim.

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)

O 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
@Todos: Ninguém me falou sobre o erro absoluto de código em Main.java :(

o problema pode ser a criação de um objeto de lista
Kemal Duran

1
[eons depois] em meu aplicativo de inicialização de primavera, @Access(AccessType.FIELD)(no meu caso, eu queria ir com FIELD) foi o único que resolveu
Scaramouche,

Respostas:


169

Você está usando uma estratégia de acesso a campo (determinada pela anotação @Id). Coloque qualquer anotação relacionada ao JPA logo acima de cada campo em vez da propriedade getter

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

@Arthur Ronald FD Garcia: Obrigado, funcionou muito bem. Mas, o programa agora é interrompido por um novo. object references an unsaved transient instance - save the transient instance before flushingVocê está ciente desse erro. Se não for apenas deixá-lo. Eu estou procurando.

@Arthur Ronald FD Garcia: Olá novamente, vi solução para o meu erro atual, que perguntei em meu comentário anterior. Este é o link. stackoverflow.com/questions/1667177/… A solução é incluir cascade=CascadeType.ALL. Mas para mim mostra erro e nenhuma sugestão no meu eclipse. Você sabe alguma coisa sobre isso. :)

9
@Arthur +1 Good catch @MaRaVan Você pode usar a estratégia de acesso de campo ou estratégia de acesso de propriedade, mas você tem que ser consistente dentro de uma hierarquia de classes, você não pode misturar as estratégias, pelo menos não no JPA 1.0. O JPA 2.0 torna possível misturar estratégias, mas você precisa de anotações extras (e, portanto, mais complexidade). Portanto, a recomendação é escolher uma estratégia e segui-la em seu aplicativo. Consulte 2.2.2.2. Tipo de acesso .
Pascal Thivent

@Arthur Ronald FD Garcia: Hmmmm ... Eu adicionei persistence.cascadeAgora está limpo. Mas recebo novamente o antigo erro object references an unsaved transient instance - save the transient instance before flushingANY Suggestions !!! : + |

@Todos: Ninguém me falou sobre o erro absoluto de código em Main.java :(

78

Adicionar o @ElementCollectionao campo Lista resolveu este problema:

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

5
+ targetClassnão é necessário, pois você mencionou o tipo da lista<Integer>
O.Badr

1
Parece ser necessário, porque eu estava procurando por uma solução exatamente para esse problema e adicionando @ElementCollection (targetClass = String.class) à minha lista simples de strings resolvi o problema.
Angel O'Sphere

32

Problema com estratégias de acesso

Como um provedor JPA, o Hibernate pode examinar tanto os atributos da entidade (campos da instância) quanto os acessadores (propriedades da instância). Por padrão, o posicionamento da @Idanotação fornece a estratégia de acesso padrão. Quando colocado em um campo, o Hibernate assumirá o acesso baseado em campo. Colocado no getter do identificador, o Hibernate usará o acesso baseado em propriedade.

Acesso baseado em campo

Ao usar o acesso baseado em campo, adicionar outros métodos de nível de entidade é muito mais flexível porque o Hibernate não considera essa parte do estado de persistência

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

Acesso baseado em propriedade

Ao usar o acesso baseado em propriedade, o Hibernate usa os acessadores para ler e escrever o estado da entidade

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

}

Mas você não pode usar o acesso baseado em campo e baseado em propriedade ao mesmo tempo. Vai mostrar aquele erro para você

Para mais ideias, siga este


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

Eu tenho os mesmos problemas, resolvi adicionando @Access(AccessType.PROPERTY)


em meu aplicativo de inicialização de primavera, @Access(AccessType.FIELD)(no meu caso, eu queria ir com FIELD) foi o único que resolveu
Scaramouche,

2

Não se preocupe! Esse problema ocorre por causa da anotação. Em vez de acesso baseado em campo, o acesso baseado em propriedade resolve esse problema. O código da seguinte forma:

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 inserir a anotação @ElementCollection sobre sua variável de lista de matriz, conforme abaixo:

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

Eu espero que isso ajude


Isso é ótimo! Funcionou como um encanto! As outras respostas não funcionam para mim. Isso realmente funcionou. A resposta principal apenas me colocou em mais problemas que eu tive que resolver separadamente deste. Boa resposta!
Compiler v2 de

2

No meu caso, foi estúpido a falta da anotação @OneToOne, configurei @MapsId sem ela


1

Embora eu seja novo no hibernar, mas com pouca pesquisa (podemos dizer tentativa e erro) descobri que é devido a inconsistência na anotação dos métodos / campos.

quando você estiver anotando @ID na variável, certifique-se de que todas as outras anotações também sejam feitas apenas na variável e quando você estiver anotando no método getter mesmo, certifique-se de estar anotando todos os outros métodos getter apenas e não suas respectivas variáveis.


1

No caso de mais alguém pousar aqui com o mesmo problema que eu encontrei. Eu estava recebendo o mesmo erro acima:

A invocação do método init falhou; a exceção aninhada é org.hibernate.MappingException: Não foi possível determinar o tipo para: java.util.Collection, na tabela:

O Hibernate usa reflexão para determinar quais colunas estão em uma entidade. Eu tinha um método privado que começava com 'get' e retornava um objeto que também era uma entidade de hibernação. Mesmo os getters privados que você deseja que o hibernate ignore devem ser anotados com @Transient. Depois de adicionar a anotação @Transient, tudo funcionou.

@Transient 
private List<AHibernateEntity> getHibernateEntities() {
   ....
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.