Hibernate version: 3.0.3
Mapping documents:
Code:
<hibernate-mapping>
<class name="Testtable" table="t1">
<id name="id" type="int">
<column name="id" sql-type="int" not-null="true"/>
<generator class="uuid.hex"/>
</id>
<property name="name">
<column name="name" length="16" not-null="true" sql-type="varchar" />
</property>
<join table="t2" fetch="join" optional="true">
<key column="id"/>
<property name="name2">
<column name="name2" length="16" not-null="false" sql-type="varchar" />
</property>
</join>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Full stack trace of any exception that occurs:Code:
Exception in thread "main" org.hibernate.exception.ConstraintViolationException: could not insert: [Testtable]
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:74)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.entity.BasicEntityPersister.insert(BasicEntityPersister.java:1859)
at org.hibernate.persister.entity.BasicEntityPersister.updateOrInsert(BasicEntityPersister.java:1906)
at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:2139)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:75)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:137)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:726)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:320)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at HibernateTest.main(HibernateTest.java:38)
Caused by: java.sql.SQLException: Duplicate key or integrity constraint violation message from server: "Duplicate entry '2' for key 1"
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2001)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1168)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1279)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2281)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1825)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1667)
at org.hibernate.persister.entity.BasicEntityPersister.insert(BasicEntityPersister.java:1846)
... 12 more
Name and version of the database you are using:MySQL 4.0.20
The generated SQL (show_sql=true):select testtable0_.id as id0_, testtable0_.name as name0_0_, testtable0_1_.name2 as name2_1_0_
from
t1 testtable0_
left outer join
t2 testtable0_1_ on testtable0_.id=testtable0_1_.id
where
testtable0_.id=2
Debug level Hibernate log excerpt:Hello,
for join tables hibernate creates (wrong) insert statements instead of update statements, thus
i get a constraint violation when changing the data.
MySQL Dump of test table:
CREATE TABLE t1 (
id int(11) NOT NULL default '0',
name varchar(100) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM;
--
-- Dumping data for table `t1`
--
INSERT INTO t1 VALUES (1,'Andy');
INSERT INTO t1 VALUES (2,'Andy2');
--
-- Table structure for table `t2`
--
CREATE TABLE t2 (
id int(11) NOT NULL default '0',
name2 varchar(100) default NULL,
PRIMARY KEY (id)
) TYPE=MyISAM;
--
-- Dumping data for table `t2`
--
INSERT INTO t2 VALUES (1,'Andy second name');
INSERT INTO t2 VALUES (2,NULL);
The problem occures when i read the data and then update the dataset with the id 2.
<code>
Transaction tx = session.beginTransaction();
Testtable t2 = (Testtable) session.get(Testtable.class, new Integer(2));
t2.setName2("neuer name2");
session.saveOrUpdate(t2);
tx.commit();
</code>
Hibernate create the following sql statemtn to read the data :
select testtable0_.id as id0_, testtable0_.name as name0_0_, testtable0_1_.name2 as name2_1_0_
from
t1 testtable0_
left outer join
t2 testtable0_1_ on testtable0_.id=testtable0_1_.id
where
testtable0_.id=2
Problem with this statement is that hibernate cannot notice if there
is an entry in the t2 table when the name2 column has null as value (from the result set data) !!!
Because of the this hibernate creates an insert statement instead of an update
statement, which then of course, results in the exception above.
The only workaround i found so far is the following :
Add another property to the join tag that maps to the the primary key column. this was
hibernate can detect if there is row in the t2 table or not. but this is only a ugly workaround,
no real solution. So is this a bug or did i miss something ?? If you need more information
tell me.
best regards,
Andreas
fixed join tag:
Code:
<join table="t2" fetch="join" optional="true">
<key column="id"/>
<property name="name2">
<column name="name2" length="16" not-null="false" sql-type="varchar" />
</property>
<property name="dummy">
<column name="id" length="16" not-null="false" sql-type="varchar" />
</property>
</join>