Hibernate entity manager seemed to have a problem with the following attribute in my class:
Code:
class Student {
...
@OneToMany
@JoinTable(
joinColumns = {@JoinColumn(name = "student_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "course_id", referencedColumnName = "id", unique = false)})
private Map<Long, Course> skills = new HashMap<Long, Course>();
...
}
As indicated in my annotation, the foreign key "course_id" in the association table "students_courses" (created by Hibernate entity manager automatically) is supposed to be non-unique (i.e., unique=false). But Hibernate kept translating it as
unique in generating the SQL code as captured below:
create table students_courses (
students_id bigint not null,
courses_id bigint not null,
mapkey bigint,
primary key (students_id, mapkey),
unique (courses_id)
)
This caused the runtime exception for duplicate foreign key courses_id while I was trying to insert a record of another student having the same courses_id=1 as the other student already existed in the database:
[main] Executing batch size: 1
[main] com.mchange.v2.c3p0.impl.NewPooledConnection@7038b9 handling a throwable.
java.sql.BatchUpdateException: Duplicate entry '1' for key 2
The previous student's record was inserted by first adding the course whose courses_id=1 and then added the that student's record in a non-cascade fashion. Hibernate only threw exception during the second addition of another student with the same courses_id. That's because the foreign key courses_id was created as unique in the join table students_courses.
I checked the table definition in the database. It showed the following layout of attribute types in the join table:
mysql> describe students_courses;
Code:
+-------------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------+------+-----+---------+-------+
| students_id | bigint(20) | NO | PRI | | |
| courses_id | bigint(20) | NO | UNI | | |
| mapkey | bigint(20) | NO | PRI | 0 | |
+-------------+------------+------+-----+---------+-------+
Is there a way to alter this behavior in Hibernate entity manager? Or is this just another problem that I will have to bear with?
william
Hibernate version: hibernate-EntityManager3.3.1.GA
Name and version of the database you are using:mysql-5.0.45-win32.zip
Debug level Hibernate log excerpt:Code:
[main] Executing batch size: 1
[main] com.mchange.v2.c3p0.impl.NewPooledConnection@7038b9 handling a throwable.
java.sql.BatchUpdateException: Duplicate entry '1' for key 2
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1269)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:955)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:144)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)