Miscellaneous features

JPA 2.1 and Java EE 7 are such huge topics that it is impossible to give full credence to every item in the specification, however here are some miscellaneous features, which I think are well worth the pursuit. Let's start with custom JPQL functions.

Custom JPQL functions

Business applications that use a relational database have custom predefined SQL functions, which are beyond the JPA standard. In JPA 2.1, the query language has been extended to support invoking these custom functions, albeit your application is locked to a database vendor's server and schema.

SELECT a FROM Artist a, Lawyer m
WHERE FUNCTION("ContractSignedOff", a.events, m.id )

Here is the JPQL example for the custom SQL function ContractSignedOff, which is predefined, say in MySQL, and returns a result set of the Artist entities.

Down-casting entities

This feature concerns inheritance hierarchies. If the JPA provider is asked to retrieve a list of entities that are typed by a superclass U, then JPA will retrieve all entities that are subclasses of U including any that match the type U. These are the twin benefits of object class hierarchies and polymorphic queries. This is a very useful feature of object-relational mapping, except for situations where you want to filter conspicuously on attributes for certain sub-class entities.

Note

Polymorphism is the ability, in a computer programming language, to create a variable, function, or type that has more than one form.

JPA 2.1 allows filtering on a specific subclass and the specific properties of the subentity by downcasting to the subentity type. There is a new function in JPQL called TREAT() that takes a class type.

Here is an example with the recording artist entities:

SELECT a.name, e.id, e.name
  FROM Artist a, ConcertEvent e
    JOIN TREAT(e AS LiveEvent) k
  WHERE k.capacity>= 10000 AND e.artist = a

The downcast allows us to access the subclass state of the ConcertEvent entity in the FROM and WHERE clauses. The query searches for recording artists associated with live concert events LiveEvent, which have a venue capacity greater than or equal to 10000 people.

We can filter or restrict based on multiple classes in the hierarchy. Here is an example based on the business marketing user story from Chapter 5, Object Relational Mapping with JPA:

SELECT m FROM Marketing m
WHERE 
  (TREAT(m AS DirectMarketing).customerOrientation 
    = "Television Adverts" ) OR
  (TREAT(m AS AgencyMarketing).agencyBudget > 250000 )

This example retrieves data filter explicitly to the different sub-entity types of the Marketing entity.

Synchronization of persistence contexts

Applications written for JPA 2.1 can now create persistence contexts that are not synchronized with an active JTA transaction. In the earlier specifications, the entity managers and the persistence context were always automatically synchronized with the transaction. After a transaction was committed, the persistence context would write the affected entities to the database during the flush operation.

Sometimes in applications there were areas and situations where a JTA transaction is neither required nor necessary. This would be the case in a web application with a business function with a lot of operations going and where we want to delay the final commit until we are ready. We have multiple transactions going in parallel elsewhere, but this particular operation is unaffected until it joins the current transaction.

The annotation @PersistenceContext has a new attribute called synchronization. Setting its value to SynchronizationType.UNSYNCHRONIZED gives us an unsynchronized persistence context. The context will share the active JTA transaction, but it will not be synchronized to it. The changes are only applied when there is a call to EntityManager.joinTransaction().

Tip

Unsynchronized persistence context limits

There are limitations to unsynchronized persistence contexts. It is definitely possible to invoke the usual entity manager calls persist() , merge(), refresh(), and remove() calls in the thread context, but other calls that depend on a current transaction will fail immediately. The key to the unsynchronized persistence context is that an application can make changes to the entities however it wants; all you do is call joinTransaction(). By the way, a rollback() method causes all the entities associated with the persistence context to be detached.

Entity listeners with CDI

Entity listeners are POJO associated with JPA entity that allows JPA provider lifecycle events to be monitored on the target entity bean. Entity listeners have been around since JPA 1.0. The annotation @EntityListeners registered a variable argument set of POJOs against an entity. Life cycle events can be detected by adding an annotation to the method in the listener. These life cycle annotations are @PrePersist, @PostPersist, @PreUpdate, @PostUpdate, @PreRemove, and @PostRemove.

In JPA 2.1, entity listeners are now compatible with Context Dependency and Injection for the first time. So if your listeners also use CDI to inject other dependent objects, then you are in business, as this example of logging services depicts:

public class EmployeeWatchDataLogger {
  @Inject CloudServiceBean logger;

  @PrePersist
    public void prePersist(Object object) {
        logger.log("prePersist", object);
    }

    @PostPersist
    public void postPersist(Object object){
        logger.log("postPersist", object);
    }
  
    @PostLoad void onPostLoad() { /* ... */ }
    @PreUpdate void onPreUpdate() { /* ... */ }
    @PostUpdate void onPostUpdate() { /* ... */ }
    @PreRemove void onPreRemove() { /* ... */ }
    @PostRemove void onPostRemove() { /* ... */ }
    
   // JPA 2.1   
    @PostConstruct
    public void postConstruct(){
        logger.connect();
    }
  
    @PreDestroy
    public void preDestroy(){
       logger.disconnect();
    }
}

The entity listener EmployeeWatchDataLogger can be associated with the appropriate entity Employee. Here is the code for that:

@Entity
@EntityListeners(value={EmployeeWatchDataLogger.class})
public class Employee {  /* ... */ }

Native query constructor mapping

There is another new annotation called @ConstructorResult in JPA 2.1 that maps results to detached entities or non-entities. We can define a native query, which performs a SQL statement and specifies an additional argument of the SQL Result Set Mapping that is able to transform the result set into an object.

Let's suppose we want to find the association between employees and departments. Here is the code snippet that creates a native SQL to retrieve those results:

Query q = em.createNativeQuery(
"SELECT e.id, e.lastName, e.firstName, d.name as dept" +
"FROM Employee e, Department d " +
"WHERE e.department = d",
  "EmployeeDeptProjection");

In order to be of use, we define a named @SQLResultSetMapping as EmployeeDeptProjection, which instructs the JPA provider to make association between to relevant detached entity or non-entity.

@SqlResultSetMapping(
name="EmpoyeeDeptProjection",
   classes={
    @ConstructorResult(
    targetClass=EmployeeDepartProjection.class,
       columns={
        @ColumnResult(name="id"),
        @ColumnResult(name="lastName"),
        @ColumnResult(name="firstName"),
        @ColumnResult(name="dept")
        }
    )
   }
 )
class EmployeeDepartProjection {
  public void EmployeeDepartProjection( String id, 
    String lm, String fm, String d) { /*... */ }
  /* ... */
} 

JPA 2.1 provides a new @ConstructorResult annotation, which defines the target class for the entity and constructor argument. The @ColumnResult annotations map the result set columns to the constructor arguments, which must be in the order that they are specified in the Java code. The target class for @ConstructorResult for this example is a non-entity, but it can be an entity class too, in which the JPA provider creates a detached instance.

It is interesting to note that @SQLResultSetMapping accepts classes of @ConstructorResult. Also SQLResultSetMapping references can also be utilized in JPA stored procedure queries.

This is as far as we will go with JPA advanced topics for this book. Let's conclude what we have learnt in this chapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.129.218.69