ChatGPT解决这个技术问题 Extra ChatGPT

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

I'm using Hibernate for all CRUD operations in my project. It doesn't work for One-To-Many and Many-To-One relationships. It gives me the below error.

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

Then again i went through this video tutorial. It is very simple to me, in the beginning. But, i cant make it work. It also now, says

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

I have ran some searches in the internet, there someone telling its a bug in Hibernate, and some says, by adding @GenereatedValue this error ll be cleared, but it doesn't work for 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)

The 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>

@All: Nobody told me about, the utter code misplacement in Main.java :(
the problem can be the creation of list object
[eons later] in my spring boot app, @Access(AccessType.FIELD) (in my case I wanted to go with FIELD) was the only one which solved it

A
Arthur Ronald

You are using field access strategy (determined by @Id annotation). Put any JPA related annotation right above each field instead of getter property

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

@Arthur Ronald F D Garcia: Thanks, it worked great. But, the program is now stopped by new one. object references an unsaved transient instance - save the transient instance before flushing Do you aware of this error. If not just leave it. I am searching.
@Arthur Ronald F D Garcia: Hi again, i saw solution for my current error, which i asked in my previous comment. This is the link. stackoverflow.com/questions/1667177/… The solution is including cascade=CascadeType.ALL. But for me it shows error and no suggestions in my eclipse. Do you know anything about that. :)
@Arthur +1 Good catch @MaRaVan You can use either field access strategy or property access strategy but you have to be consistent within a class hierarchy, you can't mix the strategies, at least not in JPA 1.0. JPA 2.0 makes it possible to mix strategies though, but you'd need extra annotations (and thus more complexity). So the recommendation is to pick one strategy and to stick to it in your application. See 2.2.2.2. Access type.
@Arthur Ronald F D Garcia: Hmmmm... I have added persistence.cascade Now its cleared. But i again get the old error object references an unsaved transient instance - save the transient instance before flushing AnY Suggestions!!! :+|
@All: Nobody told me about, the utter code misplacement in Main.java :(
n
naXa stands with Ukraine

Adding the @ElementCollection to the List field solved this issue:

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

+ targetClassis not necessary as you mentioned the type of the list <Integer>
It seems to be necessary, because I was searching for a solution for exactly this problem, and adding @ElementCollection(targetClass=String.class) to my simple list of strings solved it.
You can use Set instead of List, it should work fine.
P
Priyantha

Problem with Access strategies

As a JPA provider, Hibernate can introspect both the entity attributes (instance fields) or the accessors (instance properties). By default, the placement of the @Id annotation gives the default access strategy. When placed on a field, Hibernate will assume field-based access. Placed on the identifier getter, Hibernate will use property-based access.

Field-based access

When using field-based access, adding other entity-level methods is much more flexible because Hibernate won’t consider those part of the persistence state

@Entity
public class Simple {

@Id
private Integer id;

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

//getter +setter
}

Property-based access

When using property-based access, Hibernate uses the accessors for both reading and writing the entity state

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

}

But you can't use both Field-based and Property-based access at the same time. It will show like that error for you

For more idea follow this


R
Renato Vasconcellos

Just insert the @ElementCollection annotation over your array list variable, as below:

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

I hope this helps


That's great! It worked like a charm! The other answers don't work for me. This really did it. The main answer just got me into more problems that I had to address separately from this one. Good answer!
S
Sirko
@Access(AccessType.PROPERTY)
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="userId")
public User getUser() {
    return user;
}

I have the same problems, I solved it by add @Access(AccessType.PROPERTY)


in my spring boot app, @Access(AccessType.FIELD) (in my case I wanted to go with FIELD) was the only one which solved it
S
S.Daineko

In my case it was stupid missing of @OneToOne annotation, i set @MapsId without it


S
ShailendraChoudhary

Though I am new to hibernate but with little research (trial and error we can say) I found out that it is due to inconsistency in annotating the methods/fileds.

when you are annotating @ID on variable make sure all other annotations are also done on variable only and when you are annotating it on getter method same make sure you are annotating all other getter methods only and not their respective variables.


s
sam

Don't worry! This problem occurs because of the annotation. Instead of Field based access, Property based access solves this problem. The code as follows:

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

}


j
jbppsu

In case anyone else lands here with the same issue I encountered. I was getting the same error as above:

Invocation of init method failed; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.Collection, at table:

Hibernate uses reflection to determine which columns are in an entity. I had a private method that started with 'get' and returned an object that was also a hibernate entity. Even private getters that you want hibernate to ignore have to be annotated with @Transient. Once I added the @Transient annotation everything worked.

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

P
Pavan

Add the schema name to the entity and it will find it. Worked for me!


P
Praytic

Neither of the listed solutions worked for me and here is why: I am using entity inheritance with property-access strategy.

@Entity(name = "spec")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula(value = "type")
public abstract class Spec extends BasicEntity { ... }

Two inheritors have a property which is not presented in the super class. One of the inheritor has JoinColumn and OneToOne annotations to consolidate Basic attribute type usage (actually Intellij IDEA highlights the field if it has not appropriate getter with JoinColumn annotation).

@Data
@Entity
@DiscriminatorValue("data")
public class DataSpec extends Spec {

    private Payload payload;

    @OneToOne
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "payload_id")
    public Payload getPayload() {
        return payload;
    }

However, the second inheritor doesn't have any annotations for this new property and somehow IDEA doesn't highlight it to warn me about the issue!

@Data
@Entity
@DiscriminatorValue("blob")
public class BlobSpec extends Spec {

    private Payload payload;
  //^^^^^^^^^^^^^^^^^^^^^^^^ No getter with @JoinColumn! Should be highlighted with static code check!

I was only able to triage the issue by debuging hibernate classes. I found out that my entity doesn't pass validation in MetadataImpl.validate method. The exception doesn't tell you about it. It only prints the error occurred in the spec table, which is not a detailed message.


N
Nisha

Just remove

mappedBy="college" in @OneToMany(targetEntity=Student.class, mappedBy="college", fetch=FetchType.EAGER)

This solve my issue. ;)


M
Mwaka Ambrose

Had the same problem, my issue was that I didn't specify the @Id annotation on the the id field.

When I annotated it, everything ran smoothly.