views:

542

answers:

2

Hi,

I have a class named Parent as follows

@Entity
public class Parent {

    @Id
    @GeneratedValue
    private Integer id;

    @Embedded
    private Message message;

}

DBA (minimal OOP knowledge) has designed both Parent and Message properties in PARENT table. Message class behaves like a @OneToOne mapping because, at some cases, according to business requirement, it has:

  • Independent lifespan of the owning entity instance (Parent class)

But @Embeddable class, by default, share the same table of the owning entity (Another approach could be use a @SecondaryTable). So, i have a @Embeddable class - share the the same table of the owning entity - that behaves like a @OneToOne - according to business requirement.

Sometimes i want to update a Parent object but I DO NOT WANT to update a Message @Embedded property due business requirement (see above). When i retrieve my updateable Parent object, its message property will be null. Then Message properties will be null in database because its lifespan is bound to the lifespan of the owning entity instance (Parent). So how can i avoid @Embedded Message property to be updatable ?

Regards,

A: 

Can you provide more details?
Normally Hibernate will NOT try to update something that did not change, e.g. if your Message wasn't touched by UI code columns it's mapped to would not be part of the UPDATE statement. If they are, that means Message was changed by your UI, and that's where you should be looking for a cause of this.

ChssPly76
When i update a Parent object in UI interface, it is ONLY a Parent object without its Message embedded object. So, when my MVC framework retrieves my updatable Parent object, its Message embedded object is null. This way, i do not want update a Message embedded object because its dependent lifecycle is bound to the owning entity class (Parent)
Arthur Ronald F D Garcia
Embedded - by definition - should always be a part of its parent. Hibernate will populate your Message object when you load the parent, so if you then set it to null in UI (why?) Hibernate will attempt to save it that way (by setting all its fields to null). You can try working around this in an Interceptor by implementing findDirty() but you might want to rethink your approach instead (either not set Message to null or replace "embedded" with "one-to-one").
ChssPly76
As said: I know @Embedded classes has its lifecycle bound to the owning entity class (Parent) but i need this requirement. In fact, i should use a @OneToOne mapping instead but DBA RESTRICTIONS have limited me. How could i implement it by using findDirty Interceptor method ? Thanks
Arthur Ronald F D Garcia
Override EmptyInterceptor.findDirty() and skip over all properties of your embedded Message object (e.g. your result array should _NOT_ contain indexes for Message object properties). Once again, I think this is an overly complicated and unnecessary solution. I can understand you not wanting to use OneToOne, but why would you nullify the Message to begin with? If this has to do with UI scopes / visibility you might be better off either using decorator class or creating a transient Message field that you'd expose to UI when needed and synchronize it with persistable Message yourself.
ChssPly76
Hi ChssPly76, Thanks for your reply. I will take your advice.
Arthur Ronald F D Garcia
A: 

Hi,

as said:

DBA (minimal OOP knowledge) has designed both Parent and Message properties in PARENT table. Message class behaves like a @OneToOne mapping because, at some cases, according to business requirement, it has:

  • Independent lifespan of the owning entity instance (Parent class)

But @Embeddable component, by default, share the same table of the owning entity (Another approach could be use a @SecondaryTable). So, i have a @Embeddable component - share the the same table of the owning entity - that behaves like a @OneToOne - according to business requirement.

So in order to support it, a workaround is introduced as follows

I have created a UpdateableParent in order to use it in UI interface. UpdateableParent only contains necessary updatable fields without its @Embedded Message property.

public class UpdateableParent {

    // Parent class properties whithout its @Embedded Message property

    // getters and setters

}

So when i retrieve my UpdateableParent object, i use Automatic dirty checking feature according to:

public class ParentRepositoryImpl implements ParentRepositoryImpl {

    // dependency injection
    private SessionFactory sessionFactory;

    // Spring transaction boundary
    public void updateParent(UpdateableParent updateableParent) {

        // load method loads a proxy Parent object
        Parent parent = (Parent) sessionFactory.openSession().load(Parent.class, updateableParent.getId());

        // Them i copy updatable parent properties to proxied parent object, nothing else
        // Automatic dirty checking only updates modified fields in proxied Parent object
        BeanUtils.copyProperties(updateableParent, parent);

    }
}

This way, only UpdateableParent properties will be updateable in database.

Regards,

Arthur Ronald F D Garcia (Java programmer)

Natal/RN (Brazil)

Arthur Ronald F D Garcia

related questions