On my way in understanding the transaction-type
attribute of persistence.xml
, i came across an issue / discrepency between hibernate-core and JPA-hibernate which looks weird.
I am not pretty sure whether it is a missing implementation with JPA of hibernate.
Let me post the comparison between the outcome of JPA implementation and the hibernate implementation of the same concept.
Environment
- Eclipse 3.5.1
- JSE v1.6.0_05
- Hibernate v3.2.3 [for hibernate core]
- Hibernate-EntityManger v3.4.0 [for JPA]
- MySQL DB v5.0
Issue
1.Hibernate core
package com.expt.hibernate.core;
import java.io.Serializable;
public final class Student implements Serializable {
private int studId;
private String studName;
private String studEmailId;
public Student(final String studName, final String studEmailId) {
this.studName = studName;
this.studEmailId = studEmailId;
}
public int getStudId() {
return this.studId;
}
public String getStudName() {
return this.studName;
}
public String getStudEmailId() {
return this.studEmailId;
}
private void setStudId(int studId) {
this.studId = studId;
}
private void setStudName(String studName) {
this.studName = stuName;
}
private void setStudEmailId(int studEmailId) {
this.studEmailId = studEmailId;
}
}
2. JPA implementaion of Hibernate
package com.expt.hibernate.jpa;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "Student_Info")
public final class Student implements Serializable {
@Id
@GeneratedValue
@Column(name = "STUD_ID", length = 5)
private int studId;
@Column(name = "STUD_NAME", nullable = false, length = 25)
private String studName;
@Column(name = "STUD_EMAIL", nullable = true, length = 30)
private String studEmailId;
public Student(final String studName, final String studEmailId) {
this.studName = studName;
this.studEmailId = studEmailId;
}
public int getStudId() {
return this.studId;
}
public String getStudName() {
return this.studName;
}
public String getStudEmailId() {
return this.studEmailId;
}
}
Also, I have provided the DB configuration properties in the associated hibernate-cfg.xml [in case of hibernate core]
and persistence.xml [in case of JPA (hibernate entity manager)]
.
create a driver and perform
add a student and
query for the list of students and print their details.
Then the issue comes when you run the driver program.
Hibernate core - output
Exception in thread "main" org.hibernate.Instant开发者_开发技巧iationException: No default constructor for entity: com.expt.hibernate.core.Student
at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:84)
at org.hibernate.tuple.PojoInstantiator.instantiate(PojoInstantiator.java:100)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.instantiate(AbstractEntityTuplizer.java:351)
at org.hibernate.persister.entity.AbstractEntityPersister.instantiate(AbstractEntityPersister.java:3604)
....
....
This exception is flashed when the driver is executed for the first time itself.
JPA Hibernate - output
First execution of the driver on a fresh DB provided the following output.
DEBUG SQL:111 -
insert
into
student.Student_Info
(STUD_EMAIL, STUD_NAME)
values
(?, ?)
17:38:24,229 DEBUG SQL:111 -
select
student0_.STUD_ID as STUD1_0_,
student0_.STUD_EMAIL as STUD2_0_,
student0_.STUD_NAME as STUD3_0_
from
student.Student_Info student0_
student list size ==> 1
1 || Jegan || jegan.k@opensource.com
second execution of the driver provided the following output.
DEBUG SQL:111 -
insert
into
student.Student_Info
(STUD_EMAIL, STUD_NAME)
values
(?, ?)
17:40:25,254 DEBUG SQL:111 -
select
student0_.STUD_ID as STUD1_0_,
student0_.STUD_EMAIL as STUD2_0_,
student0_.STUD_NAME as STUD3_0_
from
student.Student_Info student0_
Exception in thread "main" javax.persistence.PersistenceException: org.hibernate.InstantiationException: No default constructor for entity: com.expt.hibernate.jpa.Student at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:76) at driver.StudentDriver.main(StudentDriver.java:43) Caused by: org.hibernate.InstantiationException: No default constructor for entity: com.expt.hibernate.jpa.Student ....
....
Could anyone please let me know if you have encountered this sort of inconsistency?
Also, could anyone please let me know if the issue is a missing implementation with JPA-Hibernate?
~ Jegan
Well, you have a "consistent" exception:
org.hibernate.InstantiationException: No default constructor for entity: com.expt.hibernate.core.Student
Just add a default constructor on your Student entity (the JPA specification actually mandates a default constructor on mapped classes to make dynamic instantiation of the class possible by the JPA provider).
Update: (answering a comment from the OP)
yeah. i can add a default constructor and get it working but i just wanted JPA-Hibernate to tell me in the very first go not in the second run. Also, i don't really the theme behind it giving the exception during the second run and not in the first run
Honestly, I can't say why it works the first time with JPA/Hibernate and fails directly with Hibernate core (well, obviously, JPA/Hibernate didn't use dynamic instantiation on the first run but I don't know why and, actually, you skipped the interesting parts of the stacktrace :) Anyway, Hibernate and the JPA spec don't mandate exceptions to be thrown at the same time, they mandate you to provide a default constructor on your entities and you didn't. So, I wouldn't spend too much time on on this little behavioral difference as this is an implementation detail. Just build to spec and voilà! And if really you want to know, you have the source code, you have a debugger. Just use them :)
In both cases you got an error that prevented the operation, which needs the default constructor and we both know that this was the problem and what is the solution.
about the different behavior I can't answer you, you should provide more information about how you are saving the objects in both cases, maybe a session flush, or a transaction not being executed may cause the late appearance of the error using JPA!!
The class need a default constructor:
public final class Student implements Serializable {
// ...
public Student() {
super();
}
// ...
}
精彩评论