Chapter 8. Other Topics

Table of Contents

8.1. Optimistic Locking
8.2. Lifecycle Listeners
8.3. Persistence by Reachability (Cascading)
8.4. Lazy Loading
8.5. Common Properties (@MappedSuperclass)
8.6. Retrieving Collections in Order
8.7. Transient (non-persisted) Properties
8.8. Handling Exceptions

This chapter contains an assortment of other topics worth knowing about when using JPA Objects.

8.1. Optimistic Locking

Optimistic locking is supported using the JPA @Version annotation, specifying the version property of an entity class that serves as its optimistic lock value. The version is used to ensure integrity when performing the merge operation and for optimistic concurrency control. That is, if the same domain object is materialized in two concurrent sessions and modified in both, then the first update wins and the second update fails. Internally, the JPA provider (Hibernate) throws an OptimisticLockException and marks the current transaction for rollback only. This exception is caught by the JPA Objects' object store implementation.

At least, theoretically. We may need further tests here...

Only a single @Version property or field should be used per class (though JPA Objects does not enforce this). Furthermore, the @Version property should be mapped to the primary table for the entity class (though JPA Objects does not enforce this either).

The following types are supported for version properties:

  • int, Integer

  • short, Short

  • long, Long

  • Timestamp

For example:

import javax.persistence.Version;
import org.nakedobjects.applib.annotation.Optional;
...

public class Customer {

    ...

    // {{ Property: JPA version
    private Long version;
    @Optional
    @Version
    public Long getVersion() {
        return version;
    }
    public void setVersion(final Long version) {
        this.version = version;
    }
    // }}
}

The property should also be annotated as @Optional, because otherwise Naked Objects will provide a default value when the object is first created. Hibernate, on the other hand, relies on null values in the version field as one of its strategies for distinguishing transient objects from persistent ones.