Hi all,
I get a GenericJDBCException retrieving data from an object that is mapped to a table that has a foreign key to another table the has a composite primary key.
I am working with hibernate3.1.3 and Hibernate Tools 3.1.0.beta4 for eclipse 3.1.2. I did also same test with Hibernate Tools 3.2.0.beta6 with eclipse 3.2.
Here the example done using MySQL:
Code:
create table stato (
id int,
nome varchar(255)
);
alter table stato
add constraint stato_pk primary key (id);
create table provincia (
stato_id int,
id varchar(5),
nome varchar(255)
);
alter table provincia
add constraint provincia_pk primary key (id, stato_id);
alter table provincia
add constraint prov_stato_fk foreign key (stato_id) references stato (id);
create table comune (
stato_id int,
prov_id varchar(5),
id varchar(5),
nome varchar(255)
);
alter table comune
add constraint comune_pk primary key (id, prov_id, stato_id);
alter table comune
add constraint com_stato_fk foreign key (stato_id) references stato (id);
alter table comune
add constraint com_prov_fk foreign key (stato_id, prov_id) references provincia (stato_id, id);
- Stato is the first table with a simple PK that is STATO.ID
- Provincia is another table which has a composite PK (PROVINCIA.STATO_ID, PROVINCIA.ID) where STATO_ID has a FK to table STATO.
- Comune is the third table which has a composite PK (COMUNE.STATO_ID, COMUNE.PROVINCIA_ID, COMUNE.ID). Here I have a FK to (PROVINCIA.STATO_ID, PROVINCIA.ID) that causes the problem.
I used Hibernate tools to create the hibernate.cfg.xml and hibernate.reveng.xml and generated the POJO and ID classes mapping the three tables.
Hibernate Tools created classes Comune.java, ComuneId.java, Provincia.java, ProvinciaId.java, Stato.java
I did not touch anything in that classes.
When I write a test like this:
ComuneId comId = new ComuneId("CM_01", "PR_01", 13);
Comune comune = (Comune) session.load(Comune.class, comId);
Provincia provincia = comune.getProvincia();
Doing instruction comune.getProvincia() I get the GenericJDBCException
SQL statement issued by Hibernate is:
Hibernate: select comune0_.id as id2_0_, comune0_.prov_id as prov2_2_0_, comune0_.stato_id as stato3_2_0_, comune0_.nome as nome2_0_ from test.comune comune0_ where comune0_.id=? and comune0_.prov_id=? and comune0_.stato_id=?
could not load an entity: [cosm.example.component.stradario.ent.pom.plc.Comune#component[id,provId,statoId]{statoId=13, provId=PR_01, id=CM_01}]
Next exception is:
Caused by: java.sql.SQLException: Invalid value for getInt() - 'PR_01' in column 2
in column 2 "prov2_2_0_" there is a string and not an integer
Here the complete test class:
-----------------------------------------------------------------------------------------
Code:
package test;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Transaction;
import org.hibernate.classic.Session;
import cosm.example.component.stradario.ent.pom.plc.Comune;
import cosm.example.component.stradario.ent.pom.plc.ComuneId;
import cosm.example.component.stradario.ent.pom.plc.Provincia;
import cosm.example.component.stradario.ent.pom.plc.ProvinciaId;
import cosm.example.component.stradario.ent.pom.plc.Stato;
public class TestPersistence {
public static void main(String[] args) {
Session session = InitSessionFactory.getInstance().openSession();
System.out.println("Test start");
Transaction transaction = session.getTransaction();
transaction.begin();
Stato stato = null;
Provincia provincia = null;
Comune comune = null;
//Search or create a new Stato
int statoId = 13;
try {
stato = (Stato) session.load(Stato.class, new Integer(statoId));
System.out.println("stato: ("
+ stato.getId()
+", "+stato.getNome()
+")");
}
catch (ObjectNotFoundException e) {
stato = new Stato(statoId, "STATO 13", null, null);
session.save(stato);
System.out.println("STATO CREATED: "+stato);
}
//Search or create a new Provincia
ProvinciaId provId = new ProvinciaId("PR_01", statoId);
try {
provincia = (Provincia) session.load(Provincia.class, provId);
stato = provincia.getStato();
System.out.println("provincia: ("
+ stato.getId()
+", "+stato.getNome()
+", "+provincia.getId().getId()
+", "+provincia.getNome()
+")");
}
catch (ObjectNotFoundException e) {
provincia = new Provincia(provId, stato, "PROVINCIA 01", null);
session.save(provincia);
System.out.println("PROVINCIA CREATED: "+provincia);
}
//Search or create a new Comune
ComuneId comId = new ComuneId("CM_01", "PR_01", statoId);
try {
comune = (Comune) session.load(Comune.class, comId);
/*
* Doing next instruction comune.getProvincia() I get the GenericJDBCException
* SQL statement issued by Hibernate is:
* Hibernate: select comune0_.id as id2_0_, comune0_.prov_id as prov2_2_0_, comune0_.stato_id as stato3_2_0_, comune0_.nome as nome2_0_ from test.comune comune0_ where comune0_.id=? and comune0_.prov_id=? and comune0_.stato_id=?
* could not load an entity: [cosm.example.component.stradario.ent.pom.plc.Comune#component[id,provId,statoId]{statoId=13, provId=PR_01, id=CM_01}]
* Next exception is:
* Caused by: java.sql.SQLException: Invalid value for getInt() - 'PR_01' in column 2
* in column 2 "prov2_2_0_" there is a string and not an integer
*/
provincia = comune.getProvincia();
stato = comune.getStato();
System.out.println("comune: ("
+ stato.getId()
+", "+stato.getNome()
+", "+provincia.getId()
+", "+provincia.getNome()
+", "+comune.getId().getId()
+", "+comune.getNome()
+")");
}
catch (ObjectNotFoundException e) {
comune = new Comune(comId, stato, provincia, "COMUNE 01");
session.save(comune);
System.out.println("COMUNE CREATED: "+comune);
}
transaction.commit();
session.close();
System.out.println("Done");
}
}
hibernate.cfg.xml:
-----------------------------------------------------------------------------------------
Code:
<?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>
<property name="hibernate.connection.driver_class">org.gjt.mm.mysql.Driver</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<mapping resource="Stato.hbm.xml"/>
<mapping resource="Provincia.hbm.xml"/>
<mapping resource="Comune.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Comune.hbm.xml:
-----------------------------------------------------------------------------------------
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 1-ago-2006 14.38.22 by Hibernate Tools 3.1.0.beta4 -->
<hibernate-mapping>
<class name="cosm.example.component.stradario.ent.pom.plc.Comune" table="comune" catalog="test">
<composite-id name="id" class="cosm.example.component.stradario.ent.pom.plc.ComuneId">
<key-property name="id" type="string">
<column name="id" length="5" />
</key-property>
<key-property name="provId" type="string">
<column name="prov_id" length="5" />
</key-property>
<key-property name="statoId" type="int">
<column name="stato_id" />
</key-property>
</composite-id>
<many-to-one name="stato" class="cosm.example.component.stradario.ent.pom.plc.Stato" update="false" insert="false" fetch="select">
<column name="stato_id" not-null="true" />
</many-to-one>
<many-to-one name="provincia" class="cosm.example.component.stradario.ent.pom.plc.Provincia" update="false" insert="false" fetch="select">
<column name="stato_id" not-null="true" />
<column name="prov_id" length="5" not-null="true" />
</many-to-one>
<property name="nome" type="string">
<column name="nome" />
</property>
</class>
</hibernate-mapping>
Provincia.hbm.xml:
-----------------------------------------------------------------------------------------
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 1-ago-2006 14.38.22 by Hibernate Tools 3.1.0.beta4 -->
<hibernate-mapping>
<class name="cosm.example.component.stradario.ent.pom.plc.Provincia" table="provincia" catalog="test">
<composite-id name="id" class="cosm.example.component.stradario.ent.pom.plc.ProvinciaId">
<key-property name="id" type="string">
<column name="id" length="5" />
</key-property>
<key-property name="statoId" type="int">
<column name="stato_id" />
</key-property>
</composite-id>
<many-to-one name="stato" class="cosm.example.component.stradario.ent.pom.plc.Stato" update="false" insert="false" fetch="select">
<column name="stato_id" not-null="true" />
</many-to-one>
<property name="nome" type="string">
<column name="nome" />
</property>
<set name="comunes" inverse="true">
<key>
<column name="stato_id" not-null="true" />
<column name="prov_id" length="5" not-null="true" />
</key>
<one-to-many class="cosm.example.component.stradario.ent.pom.plc.Comune" />
</set>
</class>
</hibernate-mapping>
Stato.hbm.xml:
-----------------------------------------------------------------------------------------
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 1-ago-2006 14.38.22 by Hibernate Tools 3.1.0.beta4 -->
<hibernate-mapping>
<class name="cosm.example.component.stradario.ent.pom.plc.Stato" table="stato" catalog="test">
<id name="id" type="int">
<column name="id" />
<generator class="assigned" />
</id>
<property name="nome" type="string">
<column name="nome" />
</property>
<set name="provincias" inverse="true">
<key>
<column name="stato_id" not-null="true" />
</key>
<one-to-many class="cosm.example.component.stradario.ent.pom.plc.Provincia" />
</set>
<set name="comunes" inverse="true">
<key>
<column name="stato_id" not-null="true" />
</key>
<one-to-many class="cosm.example.component.stradario.ent.pom.plc.Comune" />
</set>
</class>
</hibernate-mapping>
Here the complete log plus stack trace:
-----------------------------------------------------------------------------------------
Code:
Test start
Hibernate: select stato0_.id as id0_0_, stato0_.nome as nome0_0_ from test.stato stato0_ where stato0_.id=?
stato: (13, STATO 13)
Hibernate: select provincia0_.id as id1_0_, provincia0_.stato_id as stato2_1_0_, provincia0_.nome as nome1_0_ from test.provincia provincia0_ where provincia0_.id=? and provincia0_.stato_id=?
provincia: (13, STATO 13, PR_01, PROVINCIA 01)
Hibernate: select comune0_.id as id2_0_, comune0_.prov_id as prov2_2_0_, comune0_.stato_id as stato3_2_0_, comune0_.nome as nome2_0_ from test.comune comune0_ where comune0_.id=? and comune0_.prov_id=? and comune0_.stato_id=?
org.hibernate.exception.GenericJDBCException: could not load an entity: [cosm.example.component.stradario.ent.pom.plc.Comune#component[id,provId,statoId]{statoId=13, provId=PR_01, id=CM_01}]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:103)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1799)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:47)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:41)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:2730)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:365)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:346)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:123)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:82)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:862)
at org.hibernate.impl.SessionImpl.immediateLoad(SessionImpl.java:820)
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:62)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:98)
at org.hibernate.proxy.CGLIBLazyInitializer.intercept(CGLIBLazyInitializer.java:158)
at cosm.example.component.stradario.ent.pom.plc.Comune$$EnhancerByCGLIB$$2cedec2e.getProvincia(<generated>)
at test.TestPersistence.main(TestPersistence.java:62)
Caused by: java.sql.SQLException: Invalid value for getInt() - 'PR_01' in column 2
at com.mysql.jdbc.ResultSet.getIntFromString(ResultSet.java:2419)
at com.mysql.jdbc.ResultSet.getNativeInt(ResultSet.java:3727)
at com.mysql.jdbc.ResultSet.getInt(ResultSet.java:2338)
at com.mysql.jdbc.ResultSet.getInt(ResultSet.java:2353)
at org.hibernate.type.IntegerType.get(IntegerType.java:28)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:113)
at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:102)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
at org.hibernate.type.ComponentType.hydrate(ComponentType.java:506)
at org.hibernate.type.ComponentType.nullSafeGet(ComponentType.java:229)
at org.hibernate.type.ManyToOneType.hydrate(ManyToOneType.java:95)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:1899)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1372)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1300)
at org.hibernate.loader.Loader.getRow(Loader.java:1197)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:569)
at org.hibernate.loader.Loader.doQuery(Loader.java:689)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)
... 14 more
Exception in thread "main"
Any hint?
Is this a known bug?
Thanks a lot,
Marco.