-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 
Author Message
 Post subject: Embedded, AttributeOverrides and Transient properties
PostPosted: Mon Mar 20, 2006 1:28 am 
Newbie

Joined: Wed Nov 26, 2003 4:41 pm
Posts: 12
Hi all,

I have a class that holds an embedded object, but the embedded object containts a property that is always null for this class, and so I want to override the @Column mapping with a @Transient 'mapping'. As far as I can see this isn't possible and it almost feels like a limitation in the spec.

Obviously with the old way of mapping through config files I can just exclude it from my config. However to do that here I effectively need a new class.

Does anyone have any suggestions for this?

cheers
dim


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 20, 2006 7:00 pm 
Newbie

Joined: Wed Nov 26, 2003 4:41 pm
Posts: 12
Posting here in case someone else finds themselves looking for a workaround. At the moment I'm mapping the property in question as updateable=false, insertable=false and mapping it to a column that does exist. Then using Lifecycle I'm setting the property to null on load so it ends up how I want it. A nasty hack, but it is "working" for now.

I also have the opposite problem (a component with a property mapped as transient that I want to map to a column) and I'm not sure how to handle that either. Any ideas?

cheers
dim


Top
 Profile  
 
 Post subject: potential patch?
PostPosted: Mon Mar 20, 2006 7:47 pm 
Newbie

Joined: Wed Nov 26, 2003 4:41 pm
Posts: 12
Hi again,

I assume that I'm writing this to Emmanual, but would be interested in hearing anyone's thoughts.

At the moment it is possible to override column configuration using the @AttributeOverrides annotation. What I'd like to do is make it possible to override a @Transient annotation somehow. I'm thinking something like:
Code:
@Embeddable class Foo
{
  @Transient String firstName;
  @Column String lastName;
}

@Entity class Bar
{
  @Id Long id;
 
  @Embedded
  @TransientOverrides({
    @TransientOverride(name="firstName", transient = false)})
  Foo foo;
}


I haven't fully thought this through, but it seems like a reasonable enough suggestion. I'm looking at PropertyInferredData.execute(boolean) as the method that I'd need to change.

Any advice/suggestions before I dive in and try to make a patch. Obviously @TransientOverrides and @TransientOverride would be hibernate specific annotaions.

cheers
dim


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 27, 2006 11:46 am 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
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

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 09, 2006 7:21 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Hi guys,
I kinda think that such a requirement is sort of nasty.
You somehow break the relationship between the object model and the relational model by changing a logical semantic (@Id, @Transient),a nd I feel uncomfortable about that.
Overriding had always in mind the ability to change a column name, nothing else.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 09, 2006 2:15 pm 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
What do I do if I want to embed a object in some cases and use it stand alone in other cases? To do this, I need to have the id attribute ignored when embedding the object. This is supported easily with .hbm.xml files since I explicitly list the properties I want to persist in each case. With annotations, as they stand now, this is not possible.

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 10, 2006 7:17 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Yes but having the same object threated as both an entity and an embedded object smells like a design flaw. It means a given concept is treated in 2 different ways in your database

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 10, 2006 8:51 pm 
Newbie

Joined: Thu Jun 22, 2006 5:19 pm
Posts: 8
Well, what if, for efficiency reasons, I wanted a Person to embed his home and work addresses since I was going to access those every time I used the Person class, but then I wanted their favorite shopping location as a reference since I only look at it infrequently (say in a special report). Say I keep the person table in its own table space separate from the shopping address table to optimize performance? I could use a join to fetch both person and addresses at the same time, but that's not as fast as direct embedding.

I don't think this should be treated as a design flaw. I think it is a problem to have the annotations of the object model drive the table/database layout. An object-relational mapping tool should do just that, allow one to map their objects to a database layout. If I wanted a object-oriented database, then I could rewind the clock 10 years and use ObjectStore or Versant.

_________________
John Dillenburg
University of Illinois at Chicago
Department of Computer Science


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jul 16, 2006 12:30 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
For this particular optimization you'll have to fail abck to hbm xml files.

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Embedded, AttributeOverrides and Transient properties
PostPosted: Thu Jul 08, 2010 6:32 am 
Newbie

Joined: Thu Jul 06, 2006 8:04 am
Posts: 14
Its an old thread, but still desired for my purposes where I have a MyDate which has a MyTime object. The reason for these objects is that sometimes I want to store dates without a year (eg annual events). Both are marked appropriately with Embeddable and Embedded (they are not meant to be used as separate entities in the db).

Code:
MyDate {
int day
int month
int year
@Embedded
MyTime
}

@Entity
SomeClass {
@Embedded
@TransientOverride(MyTime...)
MyDate



Often MyTime is not needed - is this possible in annotation, or should I create a redundant field in the db of hour and minute?

Thanks


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 10 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.