org.hibernate.MappingException: ไม่สามารถระบุประเภทสำหรับ: java.util.List ที่โต๊ะ: วิทยาลัยสำหรับคอลัมน์: [org.hibernate.mapping.Column (นักเรียน)]


97

ฉันใช้ไฮเบอร์เนตสำหรับการดำเนินการ CRUD ทั้งหมดในโปรเจ็กต์ของฉัน ใช้ไม่ได้กับความสัมพันธ์แบบหนึ่งต่อกลุ่มและหลายต่อหนึ่ง มันทำให้ฉันมีข้อผิดพลาดด้านล่าง

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

จากนั้นอีกครั้งฉันได้ดูวิดีโอสอนนี้ มันง่ายมากสำหรับฉันในตอนแรก แต่ฉันไม่สามารถทำให้มันใช้งานได้ ตอนนี้ยังกล่าวว่า

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

ฉันทำการค้นหาในอินเทอร์เน็ตมีบางคนแจ้งข้อผิดพลาดใน Hibernateและบางคนบอกว่าโดยการเพิ่ม@GenereatedValueข้อผิดพลาดนี้จะถูกล้าง แต่มันไม่ได้ผลสำหรับฉัน

วิทยาลัย 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();
  }


}

คอนโซล:

 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>


1
@ All: ไม่มีใครบอกฉันเกี่ยวกับการวางรหัสผิดพลาดใน Main.java :(

ปัญหาอาจเป็นการสร้างวัตถุรายการ
Kemal Duran

1
[eons ต่อมา] ในแอป Spring Boot ของฉัน@Access(AccessType.FIELD)(ในกรณีของฉันฉันต้องการไปกับ FIELD) เป็นเพียงหนึ่งเดียวที่แก้ไขได้
Scaramouche

คำตอบ:


176

คุณกำลังใช้กลยุทธ์การเข้าถึงฟิลด์ (กำหนดโดยคำอธิบายประกอบ @Id) ใส่คำอธิบายประกอบที่เกี่ยวข้องกับ JPA เหนือแต่ละฟิลด์แทนคุณสมบัติ getter

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

@Arthur Ronald FD Garcia: ขอบคุณมันทำงานได้ดีมาก แต่ตอนนี้โปรแกรมหยุดใหม่แล้ว object references an unsaved transient instance - save the transient instance before flushingคุณทราบข้อผิดพลาดนี้หรือไม่ ถ้าไม่ปล่อยไว้เฉยๆ ฉันกำลังค้นหา.

@Arthur Ronald FD Garcia: สวัสดีอีกครั้งฉันเห็นวิธีแก้ปัญหาสำหรับข้อผิดพลาดปัจจุบันของฉันซึ่งฉันถามในความคิดเห็นก่อนหน้านี้ นี่คือลิงค์ stackoverflow.com/questions/1667177/…วิธีแก้ปัญหา ได้แก่cascade=CascadeType.ALL. แต่สำหรับฉันมันแสดงข้อผิดพลาดและไม่มีคำแนะนำในคราสของฉัน คุณรู้อะไรเกี่ยวกับเรื่องนั้น :)

10
@Arthur +1 Good catch @MaRaVan คุณสามารถใช้กลยุทธ์การเข้าถึงข้อมูลหรือกลยุทธ์การเข้าถึงคุณสมบัติ แต่คุณต้องสอดคล้องกันภายในลำดับชั้นคุณไม่สามารถผสมผสานกลยุทธ์ได้อย่างน้อยก็ไม่ใช่ใน JPA 1.0 JPA 2.0 ทำให้สามารถผสมผสานกลยุทธ์ได้ แต่คุณต้องมีคำอธิบายประกอบเพิ่มเติม (และมีความซับซ้อนมากขึ้น) ดังนั้นคำแนะนำคือเลือกหนึ่งกลยุทธ์และยึดติดกับมันในแอปพลิเคชันของคุณ ดู2.2.2.2 ประเภทการเข้าถึง
Pascal Thivent

@Arthur Ronald FD Garcia: อืม ... ฉันได้เพิ่มpersistence.cascadeแล้วตอนนี้มันเคลียร์แล้ว แต่ฉันได้รับข้อผิดพลาดเก่าอีกครั้งobject references an unsaved transient instance - save the transient instance before flushingคำแนะนำ AnY !!! : + |

@ All: ไม่มีใครบอกฉันเกี่ยวกับการวางรหัสผิดพลาดใน Main.java :(

79

การเพิ่มช่อง@ElementCollectionลงในรายการช่วยแก้ปัญหานี้ได้:

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

5
+ targetClassไม่จำเป็นตามที่คุณกล่าวถึงประเภทของรายการ<Integer>
O.Badr

1
ดูเหมือนว่าจะจำเป็นเพราะฉันกำลังค้นหาวิธีแก้ปัญหานี้และเพิ่ม @ElementCollection (targetClass = String.class) ในรายการสตริงง่ายๆของฉันแก้ไขได้
Angel O'Sphere

33

ปัญหาเกี่ยวกับกลยุทธ์การเข้าถึง

ในฐานะผู้ให้บริการ JPA ไฮเบอร์เนตสามารถวิเคราะห์ทั้งแอตทริบิวต์เอนทิตี (ช่องอินสแตนซ์) หรือตัวเข้าถึง (คุณสมบัติอินสแตนซ์) ตามค่าเริ่มต้นตำแหน่งของ@Idคำอธิบายประกอบจะให้กลยุทธ์การเข้าถึงเริ่มต้น เมื่อวางบนฟิลด์ไฮเบอร์เนตจะถือว่าการเข้าถึงตามฟิลด์ Hibernate จะใช้การเข้าถึงตามคุณสมบัติ

การเข้าถึงตามฟิลด์

เมื่อใช้การเข้าถึงตามฟิลด์การเพิ่มเมธอดระดับเอนทิตีอื่น ๆ จะมีความยืดหยุ่นมากกว่ามากเนื่องจากไฮเบอร์เนตจะไม่พิจารณาส่วนนั้นของสถานะการคงอยู่

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

การเข้าถึงตามคุณสมบัติ

เมื่อใช้การเข้าถึงตามคุณสมบัติไฮเบอร์เนตจะใช้ตัวเข้าถึงสำหรับทั้งการอ่านและการเขียนสถานะเอนทิตี

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

}

แต่คุณไม่สามารถใช้ทั้งการเข้าถึงตามฟิลด์และตามคุณสมบัติในเวลาเดียวกันได้ มันจะแสดงเหมือนข้อผิดพลาดนั้นสำหรับคุณ

สำหรับแนวคิดเพิ่มเติมตามนี้


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

ฉันมีปัญหาเดียวกันฉันแก้ไขได้โดยการเพิ่ม @Access(AccessType.PROPERTY)


ในแอปสปริงบูตของฉัน@Access(AccessType.FIELD)(ในกรณีของฉันฉันต้องการไปกับ FIELD) เป็นหนึ่งเดียวที่แก้ไขได้
Scaramouche

2

ไม่ต้องกังวล! ปัญหานี้เกิดขึ้นเนื่องจากคำอธิบายประกอบ แทนที่จะเป็นการเข้าถึงตามฟิลด์การเข้าถึงตามคุณสมบัติจะช่วยแก้ปัญหานี้ได้ รหัสดังต่อไปนี้:

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

เพียงใส่คำอธิบายประกอบ @ElementCollection เหนือตัวแปรรายการอาร์เรย์ของคุณดังต่อไปนี้:

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

ฉันหวังว่านี่จะช่วยได้


เยี่ยมมาก! มันทำงานได้อย่างมีเสน่ห์! คำตอบอื่น ๆ ไม่ได้ผลสำหรับฉัน สิ่งนี้ทำได้จริงๆ คำตอบหลักทำให้ฉันมีปัญหามากขึ้นที่ฉันต้องแยกจากปัญหานี้ คำตอบที่ดี!
Compiler v2

1

แม้ว่าฉันจะยังใหม่ในการจำศีล แต่มีการค้นคว้าเพียงเล็กน้อย (เราสามารถพูดได้ว่าลองผิดลองถูก) ฉันพบว่าเกิดจากความไม่สอดคล้องกันในการใส่คำอธิบายประกอบวิธีการ / ไฟล์

เมื่อคุณใส่คำอธิบายประกอบ @ID บนตัวแปรตรวจสอบให้แน่ใจว่าคำอธิบายประกอบอื่น ๆ ทั้งหมดทำบนตัวแปรเท่านั้นและเมื่อคุณใส่คำอธิบายประกอบด้วยวิธี getter เดียวกันตรวจสอบให้แน่ใจว่าคุณใส่คำอธิบายประกอบเมธอด getter อื่น ๆ ทั้งหมดเท่านั้นไม่ใช่ตัวแปรตามลำดับ


1

เผื่อมีใครเข้ามาที่นี่ด้วยปัญหาเดียวกันกับที่ฉันพบ ฉันได้รับข้อผิดพลาดเดียวกันกับด้านบน:

การเรียกใช้วิธีการเริ่มต้นล้มเหลว ข้อยกเว้นที่ซ้อนกันคือ org.hibernate.MappingException: ไม่สามารถกำหนดประเภทสำหรับ: java.util.Collection ที่ตาราง:

ไฮเบอร์เนตใช้การสะท้อนเพื่อกำหนดว่าคอลัมน์ใดอยู่ในเอนทิตี ฉันมีเมธอดส่วนตัวที่เริ่มต้นด้วย 'get' และส่งคืนอ็อบเจกต์ที่เป็นเอนทิตีไฮเบอร์เนตด้วย แม้แต่ตัวรับส่วนตัวที่คุณต้องการให้ไฮเบอร์เนตละเว้นก็ต้องใส่คำอธิบายประกอบด้วย @Transient เมื่อฉันเพิ่มคำอธิบายประกอบ @Transient ทุกอย่างก็ใช้ได้

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

1

ในกรณีของฉันมันโง่ที่ไม่มีคำอธิบายประกอบ @OneToOne ฉันตั้งค่า @MapsId โดยไม่มีมัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.