org.hibernate.MappingException: nie można określić typu dla: java.util.List, w tabeli: College, dla kolumn: [org.hibernate.mapping.Column (studenci)]

97

Używam Hibernate'a do wszystkich operacji CRUD w moim projekcie. To nie działa w przypadku relacji jeden do wielu i wiele do jednego. Daje mi poniższy błąd.

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

Potem ponownie przejrzałem ten samouczek wideo . Na początku jest to dla mnie bardzo proste. Ale nie mogę tego zrobić. Mówi się, że to również teraz

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

Przeprowadziłem kilka wyszukiwań w Internecie, tam ktoś mówi, że to błąd w Hibernate , a niektórzy mówią, że dodając @GenereatedValue ten błąd zostanie wyczyszczony, ale dla mnie nie działa.

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


}

Konsola:

 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>

Karl Richter
źródło
1
@Wszystkie: Nikt mi nie powiedział o błędnym umieszczeniu kodu w Main.java :(
problemem może być utworzenie obiektu listy
Kemal Duran
1
[eony później] w mojej wiosennej aplikacji rozruchowej @Access(AccessType.FIELD)(w moim przypadku chciałem korzystać z FIELD) był jedynym, który go rozwiązał
Scaramouche

Odpowiedzi:

177

Używasz strategii dostępu do pola (określanej przez adnotację @Id). Umieść adnotację związaną z JPA bezpośrednio nad każdym polem zamiast właściwości pobierania

@OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)
private List<Student> students;
Arthur Ronald
źródło
@Arthur Ronald FD Garcia: Dzięki, zadziałało świetnie. Ale program został teraz zatrzymany przez nowy. object references an unsaved transient instance - save the transient instance before flushingCzy wiesz o tym błędzie. Jeśli nie, po prostu to zostaw. Szukam.
@Arthur Ronald FD Garcia: Cześć ponownie, widziałem rozwiązanie dla mojego obecnego błędu, o który zapytałem w poprzednim komentarzu. To jest link. stackoverflow.com/questions/1667177/… Rozwiązanie obejmuje cascade=CascadeType.ALL. Ale dla mnie pokazuje błąd i brak sugestii w moim zaćmieniu. Wiesz coś o tym. :)
10
@Arthur +1 Dobry chwyt @MaRaVan Możesz użyć strategii dostępu do pola lub strategii dostępu do nieruchomości, ale musisz być konsekwentny w hierarchii klas, nie możesz mieszać strategii, przynajmniej nie w JPA 1.0. JPA 2.0 umożliwia jednak mieszanie strategii, ale potrzebujesz dodatkowych adnotacji (a tym samym większej złożoności). Dlatego zalecamy wybranie jednej strategii i trzymanie się jej w swojej aplikacji. Patrz 2.2.2.2. Typ dostępu .
Pascal Thivent,
@Arthur Ronald FD Garcia: Hmmmm ... Dodałem persistence.cascadeTeraz jest wyczyszczony. Ale znowu otrzymuję stary błąd object references an unsaved transient instance - save the transient instance before flushingWSZELKIE sugestie !!! : + |
@Wszystkie: Nikt mi nie powiedział o błędnym umieszczeniu kodu w Main.java :(
80

Dodanie pola @ElementCollectiondo listy rozwiązało ten problem:

    @Column
    @ElementCollection(targetClass=Integer.class)
    private List<Integer> countries;
Biggy_java2
źródło
5
+ targetClassnie jest konieczne, ponieważ wspomniałeś o rodzaju listy<Integer>
O.Badr
1
Wydaje się to konieczne, ponieważ szukałem rozwiązania właśnie dla tego problemu i dodając @ElementCollection (targetClass = String.class) do mojej prostej listy ciągów, rozwiązałem go.
Angel O'Sphere,
33

Problem ze strategiami dostępu

Jako dostawca JPA, Hibernate może przeglądać zarówno atrybuty encji (pola instancji), jak i akcesory (właściwości instancji). Domyślnie umieszczenie @Idadnotacji zapewnia domyślną strategię dostępu. Po umieszczeniu na polu Hibernate przyjmie dostęp na podstawie pola. Umieszczony na getterze identyfikatora, Hibernate będzie używał dostępu opartego na właściwościach.

Dostęp w terenie

W przypadku korzystania z dostępu opartego na polach dodanie innych metod na poziomie encji jest znacznie bardziej elastyczne, ponieważ Hibernate nie bierze pod uwagę tych części stanu trwałości

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

Dostęp w oparciu o własność

Korzystając z dostępu opartego na właściwościach, Hibernate używa metod dostępu do odczytu i zapisu stanu jednostki

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

}

Ale nie możesz jednocześnie korzystać z dostępu opartego na polach i właściwościach. Pokaże ci się taki błąd

Więcej pomysłów znajdziesz w tym artykule

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

Mam te same problemy, rozwiązałem je dodając @Access(AccessType.PROPERTY)

user2406031
źródło
w mojej wiosennej aplikacji rozruchowej @Access(AccessType.FIELD)(w moim przypadku chciałem korzystać z FIELD) był jedynym, który go rozwiązał
Scaramouche
2

Nie martw się! Ten problem występuje z powodu adnotacji. Zamiast dostępu opartego na polach dostęp oparty na właściwości rozwiązuje ten problem. Kod w następujący sposób:

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

}

kamień Aaron
źródło
2

Po prostu wstaw adnotację @ElementCollection nad zmienną z listą tablic, jak poniżej:

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

mam nadzieję, że to pomoże

Renato Vasconcellos
źródło
To wspaniale! Zadziałało jak urok! Inne odpowiedzi mi nie pasują. To naprawdę zadziałało. Główna odpowiedź po prostu doprowadziła mnie do większej liczby problemów, którymi musiałem się zająć niezależnie od tego. Dobra odpowiedź!
Kompilator v2
1

Chociaż jestem nowy w hibernacji, ale po niewielkich badaniach (można powiedzieć, prób i błędów) odkryłem, że jest to spowodowane niekonsekwencją w adnotacjach do metod / pól.

kiedy adnotujesz @ID na zmiennej, upewnij się, że wszystkie inne adnotacje są również wykonywane tylko na zmiennej, a kiedy dodajesz adnotację w metodzie getter, upewnij się, że adnotujesz tylko wszystkie inne metody pobierające, a nie odpowiadające im zmienne.

ShailendraChoudhary
źródło
1

Na wypadek, gdyby ktoś inny wylądował tutaj z tym samym problemem, z którym się spotkałem. Otrzymywałem ten sam błąd co powyżej:

Wywołanie metody init nie powiodło się; zagnieżdżony wyjątek to org.hibernate.MappingException: nie można określić typu dla: java.util.Collection, w tabeli:

Hibernate wykorzystuje odbicie, aby określić, które kolumny są w jednostce. Miałem prywatną metodę, która zaczynała się od „get” i zwróciła obiekt, który również był hibernacją. Nawet prywatne metody pobierające, które mają być ignorowane przez hibernację, muszą być opatrzone adnotacją @Transient. Po dodaniu adnotacji @Transient wszystko działało.

@Transient 
private List<AHibernateEntity> getHibernateEntities() {
   ....
}
jbppsu
źródło
1

W moim przypadku głupio brakowało adnotacji @OneToOne, ustawiam @MapsId bez niego

S.Dayneko
źródło