Archive for the ‘hibernate’ Category

Hibernate 3 / EJB3 annotations severely limited?

Tuesday, March 14th, 2006

Apparently modelling a simple parent child relationship where the primary key of the parent is part of a composite key on the child is not possible using EJB3 annotations.

For enterprise beans this seems like a very large oversight. I know a couple of projects that use this idiom for their relational structures. It feels odd that this is not part of the current implementation of the EJB3 annotations. For those trying out Hibernate, here is a forum post regarding this problem.

The problem I am facing is in my opinion a very basic mapping case. It seems strange and very limiting that it is not part of the annotations.

For those that don’t get what I am referring to, consider the following:

@Entity
public class Parent {
    @Id
    Long id;

    @OneToMany
    @JoinColumn(name = "parent")
    List children;
}

@Entity
public class Child {
    @ManyToOne()
    @JoinColumn(nullable = false, insertable = false, updatable = false, name = "parent")
    Parent parent;

    Long childNr;
}

Now try to make both the parent and the childNr part of the primary key of the child using annotations.

And what seems even worse, is that you need to define a composite key class especially for using a composite key. Apparently that is needed for sending over the object’s key across the network.

Annotations are very useful, and we have been able to build large parts of our system using them. So don’t see this as a rejection of the technology as a whole. I enjoy working with annotations for mapping purposes but they just don’t seem to be quite there yet.

What? No JavaDoc for javax.persistence?

Monday, March 13th, 2006

After searching the ‘net for some documentation on the upcoming and much touted JEE5 persistence API I couldn’t help noticing the
ABSOLUTE ABSENCE OF API DOCUMENTATION
on the whole of the javax.persistence package. Probably the most popular, and awaited package from the whole JEE5 stack has no documentation.

This is sub par from Sun and the persistence API spec. Am I the first one that thinks this is a serious oversight? Will this not hinder adoption of the persistence API?

Lot’s of people rightfully criticize open source projects for not writing (enough) documentation. I know the Wicket documentation could be better, but at least our API docs are quite solid.

Wicket goodie: Hibernate Versioned Form

Monday, February 13th, 2006

Last week I had the pleasure to add optimistic locking to our web application, using automatic versioning in Hibernate. What we want is to detect a stale object when a form is submitted and displaying the new representation from the database, overriding the submitted data.

So when two people open an edit form for the same contact, and the first to submit renames the contact from ‘Foo’ to ‘Bar’, the database will be updated, changing the name from ‘Foo’ to ‘Bar’. When the second user tries to save the contact, changing the name from ‘Foo’ (that was the last information he got) to ‘John’, we want to show him that the data has been changed by someone else, and show him the new information, disregarding his change to ‘John’.

Now, how would you do this for all your forms in your application without resorting to the usual hidden field option? Wicket has allowed me to do such a thing without much trouble. Here’s a short description.

public class VersionedForm extends Form {
    private Long version;

    public VersionedForm(String id, IModel model) {
        super(id, model);
        version = getVersion();
    }

    protected void validate() {
        Long newVersion = getVersion();

        if(!newVersion.equals(version)) {
            // new method in 1.2
            clearInput();

            // detaches the model of the page, and evicts the
            // object from the hibernate session
           ((MyPage) getPage()).reloadModel();

           // copy the new version onto the form
           version = newVersion;
           error("Someone else modified the object already, try again");
        } else {
           // do the default form processing.
           super.validate();
        }
    }
    private Long getVersion() {
        // get the version of the model object
        // either through reflection or just a cast to your base object
        return ((MyBaseObject)getModelObject()).getVersion();
    }
}

Here you see three important steps:

1. set the current version in the constructor
2. check the version in the validate() method
3. reload the object when it is not valid, and clear the user input

Retrieving the version can be implemented using reflection, searching for the @version annotation, or by implementing a custom interface IVersioned, or something to your liking.

The reloading of the object and evicting it from the Hibernate session is something we implement at the page level, as we always put the object that is edited into the page model.

The best part is that in any edit page we have, we now just have to subclass our forms from VersionedForm, and we have instant optimistic locking.