Two tables with composite primary keys and OneToOne mapping throws an exception.
Beneath you could find a standalone class to reproduce the problem.
The Problem is in
org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:34)
where hibernate tries to access the pk field but using the wrong reflected field.
E.g. it tries TableAPk.field on TableB object.
Hibernate version:
hibernate3 cvs 2005-03-18
annotations cvs 2005-03-18
Mapping documents:
Code:
@OneToOne(fetch=FetchType.LAZY)
@JoinColumns ({
@JoinColumn(name = "KLIENT_ID", referencedColumnName = "KLIENT_ID"),
@JoinColumn(name = "KND_ID", referencedColumnName = "KND_ID")
})
private Mdkndvst mdkndvst;
Code between sessionFactory.openSession() and session.close():Full stack trace of any exception that occurs:Code:
Exception in thread "main" org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.ops.Premium.model.po.MdkndvstPk.klientId
at org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:34)
at org.hibernate.tuple.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:61)
at org.hibernate.tuple.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:67)
at org.hibernate.tuple.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:50)
at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:257)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:158)
at org.hibernate.engine.EntityKey.getHashCode(EntityKey.java:68)
at org.hibernate.engine.EntityKey.<init>(EntityKey.java:41)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:73)
at org.hibernate.impl.SessionImpl.internalLoadOneToOne(SessionImpl.java:590)
at org.hibernate.type.OneToOneType.resolveIdentifier(OneToOneType.java:79)
at org.hibernate.type.EntityType.resolve(EntityType.java:264)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:105)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:495)
at org.hibernate.loader.Loader.doQuery(Loader.java:414)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:209)
at org.hibernate.loader.Loader.doList(Loader.java:1567)
at org.hibernate.loader.Loader.list(Loader.java:1536)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:111)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1252)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:299)
at org.hibernate.impl.CriteriaImpl.uniqueResult(CriteriaImpl.java:432)
at com.ops.lib.model.PersistentObjectQuery.getUnique(PersistentObjectQuery.java:52)
at com.ops.Premium.model.dbo.MdkndDBO.getForWwwLogin(MdkndDBO.java:32)
at com.ops.Premium.HbmTest.exe(HbmTest.java:60)
Name and version of the database you are using:Oracle 9
Code:
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
import org.hibernate.Session;
import org.hibernate.tool.hbm2ddl.SchemaUpdate;
import org.hibernate.dialect.HSQLDialect;
import javax.persistence.AccessType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.OneToOne;
import javax.persistence.Id;
import javax.persistence.GeneratorType;
import javax.persistence.Embeddable;
import java.util.List;
import java.util.Iterator;
import java.io.Serializable;
public class HbmP1
{
@Entity(access = AccessType.FIELD)
public static class TableA implements Serializable
{
@Id(generate=GeneratorType.NONE)
private TableAPk key;
private String value;
@OneToOne(fetch=FetchType.LAZY)
@JoinColumns ({
@JoinColumn(name = "companyId", referencedColumnName = "companyId"),
@JoinColumn(name = "customerId", referencedColumnName = "customerId")
})
private TableB tableB;
public TableA()
{
}
public TableAPk getKey()
{
return key;
}
public void setKey(TableAPk key)
{
this.key = key;
}
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
public TableB getTableB()
{
return tableB;
}
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof TableA))
{
return false;
}
final TableA tableA = (TableA) o;
if (key != null ? !key.equals(tableA.key) : tableA.key != null)
{
return false;
}
return true;
}
public int hashCode()
{
return (key != null ? key.hashCode() : 0);
}
}
@Embeddable(access=AccessType.FIELD)
public static class TableAPk implements Serializable
{
private String companyId;
private String customerId;
public TableAPk()
{
}
public String getCompanyId()
{
return companyId;
}
public void setCompanyId(String companyId)
{
this.companyId = companyId;
}
public String getCustomerId()
{
return customerId;
}
public void setCustomerId(String customerId)
{
this.customerId = customerId;
}
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof TableAPk))
{
return false;
}
final TableAPk tableAPk = (TableAPk) o;
if (companyId != null ? !companyId.equals(tableAPk.companyId) : tableAPk.companyId != null)
{
return false;
}
if (customerId != null ? !customerId.equals(tableAPk.customerId) : tableAPk.customerId != null)
{
return false;
}
return true;
}
public int hashCode()
{
int result;
result = (companyId != null ? companyId.hashCode() : 0);
result = 29 * result + (customerId != null ? customerId.hashCode() : 0);
return result;
}
}
@Entity(access = AccessType.FIELD)
public static class TableB implements Serializable
{
@Id(generate=GeneratorType.NONE)
private TableBPk key;
private String value;
public TableB()
{
}
public TableBPk getKey()
{
return key;
}
public void setKey(TableBPk key)
{
this.key = key;
}
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof TableB))
{
return false;
}
final TableB tableB = (TableB) o;
if (key != null ? !key.equals(tableB.key) : tableB.key != null)
{
return false;
}
return true;
}
public int hashCode()
{
return (key != null ? key.hashCode() : 0);
}
}
@Embeddable(access=AccessType.FIELD)
public static class TableBPk implements Serializable
{
private String companyId;
private String customerId;
public TableBPk()
{
}
public String getCompanyId()
{
return companyId;
}
public void setCompanyId(String companyId)
{
this.companyId = companyId;
}
public String getCustomerId()
{
return customerId;
}
public void setCustomerId(String customerId)
{
this.customerId = customerId;
}
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof TableBPk))
{
return false;
}
final TableBPk tableBPk = (TableBPk) o;
if (companyId != null ? !companyId.equals(tableBPk.companyId) : tableBPk.companyId != null)
{
return false;
}
if (customerId != null ? !customerId.equals(tableBPk.customerId) : tableBPk.customerId != null)
{
return false;
}
return true;
}
public int hashCode()
{
int result;
result = (companyId != null ? companyId.hashCode() : 0);
result = 29 * result + (customerId != null ? customerId.hashCode() : 0);
return result;
}
}
public static void main(String[] args)
{
AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.addAnnotatedClass(TableA.class);
cfg.addAnnotatedClass(TableB.class);
cfg.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver");
cfg.setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:hbmtest");
cfg.setProperty("hibernate.dialect", HSQLDialect.class.getName());
SessionFactory factory = cfg.buildSessionFactory();
SchemaUpdate update = new SchemaUpdate(cfg);
update.execute(false, true);
Session session = factory.openSession();
TableA rec = new TableA();
TableAPk reckey = new TableAPk();
reckey.setCompanyId("A1");
reckey.setCustomerId("C2");
rec.setKey(reckey);
rec.setValue("V");
session.save(rec);
session.flush();
// ==> this needs to be done - else the bug wont happen
session.close();
session = factory.openSession();
// <==
List list = session.createCriteria(TableA.class).list();
Iterator iterList = list.iterator();
while (iterList.hasNext())
{
System.err.println(iterList.next());
}
}
}