This is a question about initilising a collection of a class with composite primary keys. It appears that hibernate is creating incorrect SQL statements... I would appreciate some help in this matter.
Hibernate version: Hibernate 3.1.2
Mapping documents:
Teacher *<-->* Student
Teacher 1<-->* TeacherStudent *<-->1 Stduent
There is many-to-many relationship between Teacher and Student. This relationship is modelled to by 2 many-to-one relationships between TeacherStudent/Teacher and TeacherStudent/Student classes.
Tables:
Code:
mysql> desc teacher;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(128) | NO | UNI | | |
+-------+--------------+------+-----+---------+----------------+
mysql> desc student;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(128) | NO | UNI | | |
+-------+--------------+------+-----+---------+----------------+
TeacherStudentBean Class
mysql> desc teacher_student;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| teacher_id | int(11) | NO | PRI | 0 | |
| student_id | int(11) | NO | PRI | 0 | |
+------------+---------+------+-----+---------+-------+
TeacherStudent Class
Code:
@Entity
@Table(name = "teacher_student")
public class TeacherStudentBean implements Serializable, com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentIf {
private static Logger log = LogService.getLogger(TeacherStudentBean.class);
private TeacherBean teacherIdTeacher;
private StudentBean studentIdStudent;
/**
* the composite primary key.
*/
private com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentPK primaryKey;
/**
* Default constructor.
*/
public TeacherStudentBean() {
}
/**
* Value object constructor.
*/
public TeacherStudentBean(com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentIf value) {
if (value != null) {
setTeacherId(value.getTeacherId());
}
if (value != null) {
setStudentId(value.getStudentId());
}
}
/**
* Creates a new bean and returns the primary key.
* If the primary key of the value object has been set, this key will be used.
* If the primary key is set to null, Hibernate's increment id generator is used for integers and longs
* and the uuid.hex generator for strings.
*
* @param value a <code>TeacherStudentIf</code>
* @return the primary key for this TeacherStudent
*/
public com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentPK create(com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentIf value) {
if (value != null) {
setTeacherId(value.getTeacherId());
}
if (value != null) {
setStudentId(value.getStudentId());
}
return value.getPrimaryKey();
}
/**
* Return the composite primary key.
*
* @return com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentPK with the primary key.
*
*/
@Id
public com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentPK getPrimaryKey() {
return primaryKey;
}
/**
* Set the composite primary key.
*
* @param primaryKey the primary key
*/
public void setPrimaryKey(com.finalist.teacherstudent.entity.teacherstudent.TeacherStudentPK primaryKey) {
this.primaryKey = primaryKey;
}
/**
* Returns the value of the <code>teacherIdTeacher</code> relation property.
*
* @return the value of the <code>teacherIdTeacher</code> relation property.
*
*/
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
@JoinColumn(name = "teacher_id")
public TeacherBean getRelationTeacherIdTeacher(){
return teacherIdTeacher;
}
/**
* Returns the value of the <code>teacherIdTeacher</code> relation property.
*
* @return the value of the <code>teacherIdTeacher</code> relation property.
*
*/
@javax.persistence.Transient
public TeacherIf getTeacherIdTeacher(){
return getRelationTeacherIdTeacher();
}
/**
* Sets the value of the <code>teacherIdTeacher</code> relation property.
*
* @param teacher a value for <code>teacherIdTeacher</code>.
*/
@javax.persistence.Transient
public void setRelationTeacherIdTeacher(TeacherBean teacher) {
this.teacherIdTeacher = teacher;
}
/**
* Sets the value of the <code>teacherIdTeacher</code> relation property.
*
* @param teacher a value for <code>teacherIdTeacher</code>.
*/
@javax.persistence.Transient
public void setTeacherIdTeacher(TeacherIf teacher) {
setRelationTeacherIdTeacher(new TeacherBean(teacher));
}
/**
* Returns the value of the <code>studentIdStudent</code> relation property.
*
* @return the value of the <code>studentIdStudent</code> relation property.
*
*/
@ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
@JoinColumn(name = "student_id")
public StudentBean getRelationStudentIdStudent(){
return studentIdStudent;
}
/**
* Returns the value of the <code>studentIdStudent</code> relation property.
*
* @return the value of the <code>studentIdStudent</code> relation property.
*
*/
@javax.persistence.Transient
public StudentIf getStudentIdStudent(){
return getRelationStudentIdStudent();
}
/**
* Sets the value of the <code>studentIdStudent</code> relation property.
*
* @param student a value for <code>studentIdStudent</code>.
*/
@javax.persistence.Transient
public void setRelationStudentIdStudent(StudentBean student) {
this.studentIdStudent = student;
}
/**
* Sets the value of the <code>studentIdStudent</code> relation property.
*
* @param student a value for <code>studentIdStudent</code>.
*/
@javax.persistence.Transient
public void setStudentIdStudent(StudentIf student) {
setRelationStudentIdStudent(new StudentBean(student));
}
/**
* Returns the value of the <code>id</code> property.
*
*/
@javax.persistence.Transient
public java.lang.Integer getTeacherId() {
if (teacherIdTeacher != null) {
return teacherIdTeacher.getId();
} else {
return null;
}
}
/**
* Sets the value of the <code>id</code> property.
*
* @param id the value for the <code>id</code> property
*/
@javax.persistence.Transient
public void setTeacherId(java.lang.Integer id) {
if (teacherIdTeacher == null) {
teacherIdTeacher = new TeacherBean();
}
teacherIdTeacher.setId(id);
}
/**
* Returns the value of the <code>id</code> property.
*
*/
@javax.persistence.Transient
public java.lang.Integer getStudentId() {
if (studentIdStudent != null) {
return studentIdStudent.getId();
} else {
return null;
}
}
/**
* Sets the value of the <code>id</code> property.
*
* @param id the value for the <code>id</code> property
*/
@javax.persistence.Transient
public void setStudentId(java.lang.Integer id) {
if (studentIdStudent == null) {
studentIdStudent = new StudentBean();
}
studentIdStudent.setId(id);
}
}
Code between sessionFactory.openSession() and session.close():The following piece of code throws the exception...
Code:
public Collection getTeacherStudentList() throws GenericBusinessException {
com.finalist.teacherstudent.HibernateQueryHelper hibernateTemplate = new com.finalist.teacherstudent.HibernateQueryHelper();
try {
String queryString = "from " + TeacherStudentBean.class.getName() + " e";
Query query = hibernateTemplate.createQuery(queryString);
List list = hibernateTemplate.list(query);
return list;
} finally {
log.debug("finished getTeacherStudentList");
}
}
create query...
Code:
public Query createQuery(String queryString) throws GenericBusinessException {
try {
return session.createQuery(queryString);
} catch (Exception e) {
String message = "Error while getting the hibernate query.";
log.error(message, e);
GenericBusinessException gbe = new GenericBusinessException(message, e);
throw gbe;
}
}
list...
Code:
public java.util.List list(Query query) throws GenericBusinessException {
try {
return query.list();
} catch (Exception e) {
String message = "Error while getting the hibernate query list.";
log.error(message, e);
GenericBusinessException gbe = new GenericBusinessException(message, e);
throw gbe;
}
}
Full stack trace of any exception that occurs:Code:
com.finalist.teacherstudent.exception.GenericBusinessException: Error while getting the hibernate query list. at com.finalist.teacherstudent.HibernateQueryHelper.list(HibernateQueryHelper.java:102) at com.finalist.teacherstudent.session.TeacherStudentFacade.getTeacherStudentList(TeacherStudentFacade.java:436) at com.finalist.teacherstudent.actions.InitTeacherStudentSearchAction.doPerform(InitTeacherStudentSearchAction.java:48) at com.finalist.util.genelv.struts.GenericAction.execute(GenericAction.java:69) at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421) at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226) at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1164) at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397) at javax.servlet.http.HttpServlet.service(HttpServlet.java:689) at javax.servlet.http.HttpServlet.service(HttpServlet.java:802) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) at filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:169) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) at com.finalist.teacherstudent.SessionFilter.doFilter(SessionFilter.java:39) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:125) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:833) at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:639) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1285) at java.lang.Thread.run(Unknown Source) Caused by: org.hibernate.exception.SQLGrammarException: could not execute query at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:65) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43) at org.hibernate.loader.Loader.doList(Loader.java:2148) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029) at org.hibernate.loader.Loader.list(Loader.java:2024) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:375) at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:308) at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:153) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1129) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79) at com.finalist.teacherstudent.HibernateQueryHelper.list(HibernateQueryHelper.java:98) ... 30 more Caused by: java.sql.SQLException: Unknown column 'teacherstu0_.teacherId' in 'field list' at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2928) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1571) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1666) at com.mysql.jdbc.Connection.execSQL(Connection.java:2994) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:936) at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1030) at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:76) at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:139) at org.hibernate.loader.Loader.getResultSet(Loader.java:1669) at org.hibernate.loader.Loader.doQuery(Loader.java:662) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224) at org.hibernate.loader.Loader.doList(Loader.java:2145) ... 38 more
Name and version of the database you are using: MySQL 5.0
The generated SQL (show_sql=true):Code:
Hibernate: select teacherstu0_.teacherId as teacherId2_, teacherstu0_.studentId
as studentId2_, teacherstu0_.teacher_id as teacher3_2_, teacherstu0_.student_id
as student4_2_ from teacher_student teacherstu0_
The interesting part is tha hibernating selecting columns teacherId and studentId which do not exist. Thus the following entry in the stack trace:
Caused by: java.sql.SQLException: Unknown column 'teacherstu0_.teacherId' in 'field list' at
Any feedback on this would be welcome.
Thank you.