Dim, I agree that it should be possible to selectively set an embedded class's fields to be transient. I've run into a case where the @Id field of an embedded class interferes with the @Id field of the parent class. I want to both embed a class and reference it as an entity. Here's a test case derived from hibernate-annotations-3.2.0.CR1/test/org/hibernate/test/annotations/TestCase.java that illustrates the problem:
Code:
public class TestHibernateEmbedded extends TestCase {
public TestHibernateEmbedded(String testName) {
super(testName);
}
public void testSimpleEmbedding()
throws Exception
{
Session s = openSession();
Transaction tx = s.beginTransaction();
EmbeddableAddress address = new EmbeddableAddress();
address.setStreetName("Privet Drive");
address.setStreetNumber("4");
PersonWithEmbeddedAddress person = new PersonWithEmbeddedAddress();
person.setAddress(address);
s.save(person); // should also save embedded addresses
s.flush();
tx.commit();
s.close();
s = openSession();
tx = s.beginTransaction();
person = (PersonWithEmbeddedAddress )s.get(
PersonWithEmbeddedAddress.class, person.getId()
);
assertNotNull("person should be in database", person);
assertNotNull("address should be in person", person.getAddress());
tx.commit();
s.close();
}
@Entity
public static class PersonWithEmbeddedAddress {
private Long id;
private EmbeddableAddress address;
@Id
@GeneratedValue
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Embedded
@AttributeOverrides({
@AttributeOverride(name="id", column=@Column(name="",insertable=false,updatable=false,columnDefinition=""))
})
EmbeddableAddress getAddress() {
return address;
}
public void setAddress(EmbeddableAddress address) {
this.address = address;
}
}
@Embeddable
public static class EmbeddableAddress {
private String streetName;
private String streetNumber;
private Integer id;
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getStreetName() {
return streetName;
}
public void setStreetName(String streetName) {
this.streetName = streetName;
}
public String getStreetNumber() {
return streetNumber;
}
public void setStreetNumber(String streetNumber) {
this.streetNumber = streetNumber;
}
}
public Class[] getMappings() {
return new Class[]{
PersonWithEmbeddedAddress.class
};
}
}
This test
fails with the exception:
Code:
IllegalArgumentException occurred while calling setter of org.sharethedrive.test.hibernate.TestHibernateEmbedded$PersonWithEmbeddedAddress.id
org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of org.sharethedrive.test.hibernate.TestHibernateEmbedded$PersonWithEmbeddedAddress.id
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:104)
at org.hibernate.tuple.AbstractEntityTuplizer.setIdentifier(AbstractEntityTuplizer.java:204)
at org.hibernate.persister.entity.AbstractEntityPersister.setIdentifier(AbstractEntityPersister.java:3373)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:53)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:108)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:537)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:525)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:521)
at org.sharethedrive.test.hibernate.TestHibernateEmbedded.testSimpleEmbedding(TestHibernateEmbedded.java:31)
at org.sharethedrive.test.hibernate.HibernateTestCase.runTest(HibernateTestCase.java:74)
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:42)
... 32 more