™ Persistence API: Portability Do’s and Don’ts Mike Keith Oracle Corp. http://otn.oracle.com/jpa

TS-4568

2007 JavaOneSM Conference | Session TS-4568 | GoalGoal

To learn more about Java™ Persistence API (JPA), what the portability issues are, and what you need to know to write more portable code.

2007 JavaOneSM Conference | Session TS-4568 | 2 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 3 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 4 Background

• Unifying POJO persistence technology into a standard enterprise API • Part of Enterprise JavaBeans™ (EJB™) 3.0 specification, but is separately documented • May be used in either Java Platform, Enterprise Edition (Java EE platform) or Java Platform, Standard Edition (Java SE platform) • Superior ease of use within host container • Client API with local transactions in Java SE platform • Service Provider Interface (SPI) for container/persistence provider pluggability

2007 JavaOneSM Conference | Session TS-4568 | 5 Primary Features

• POJO-based persistence model • Simple Java class files—not components • Supports traditional O-O modelling concepts • Inheritance, polymorphism, encapsulation, etc. • Standard abstract relational query language • Standard O/R mapping metadata • Using annotations and/or XML • Portability across providers (implementations)

2007 JavaOneSM Conference | Session TS-4568 | 6 Where Are We Now?

• JPA 1.0 finalized in May 2006 • Released as part of Java EE 5 platform • All major vendors have implemented or are working towards offering EJB 3.0 specification/JPA • Developer interest and adoption proving to be extremely strong • 80–90% of useful ORM features specified • Additional features will be added to JPA 2.0

2007 JavaOneSM Conference | Session TS-4568 | 7 Implementations

• Persistence provider vendors include: • Oracle, Sun/TopLink Essentials (RI) • JPA—EclipseLink Project • BEA Kodo/Apache OpenJPA • RedHat/JBoss • SAP JPA • JPA containers • Sun, Oracle, SAP, BEA, JBoss, Spring 2.0 • IDEs • Eclipse, NetBeans™ IDE, IntelliJ, JDeveloper

2007 JavaOneSM Conference | Session TS-4568 | 8 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 9 Forces Acting Upon Us

Portability Features

Simplicity

2007 JavaOneSM Conference | Session TS-4568 | 10 Portability vs. Added Value

Innovation Is Good! • Vendors are expected to add features their customers ask for and need • Popular features will be moved into the JPA spec • Less used features shouldn’t clutter the API Corollary 1: We will always have to live with the presence of non-standard features Corollary 2: If you are ever in the position of needing a feature that is not in the spec then you will be glad Corollary 1 is true

2007 JavaOneSM Conference | Session TS-4568 | 11 Accessing Vendor Features

• Vendor features show up in different forms • Persistence properties • Query hints • Casting to vendor-specific class • Customization code • Vendor-specific annotations • Additional proprietary XML descriptors

2007 JavaOneSM Conference | Session TS-4568 | 12 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 13 Integrating the Proprietary

• Hooks are built into JPA to support vendor- specific features at two different levels • Persistence unit properties • Query hints • Unrecognized options must be ignored by the provider • Provides source code and compile-time portability • Not necessarily semantically portable

2007 JavaOneSM Conference | Session TS-4568 | 14 Persistence Unit Properties

• Set of optional key-value properties specified in persistence. file • Apply to the entire persistence unit • May have multiple vendor properties specifying the same or different things • Property only has meaning to the vendor that defines and interprets it

2007 JavaOneSM Conference | Session TS-4568 | 15 Persistence Unit Properties

2007 JavaOneSM Conference | Session TS-4568 | 16 Query Hints

• Vendor directives may be defined statically in named query metadata (annotations or XML) • Applied at query execution time

@NamedQuery(name=“Trade.findBySymbol”, query=“SELECT t FROM Trade t “ + “WHERE t.symbol = :sym”, hints={ @QueryHint( name=“toplink.pessimistic-lock”, value=“Lock”), @QueryHint( name=“openjpa.ReadLockLevel”, value=“write”) } ) 2007 JavaOneSM Conference | Session TS-4568 | 17 Query Hints

• May be defined dynamically using the Query API • More flexible because any Java object may be passed in as the value • Lose source-code portability if object is vendor-specific

Query query = em.createQuery( “SELECT t FROM Trade t WHERE t.symbol = :sym”); query.setHint(“toplink.pessimistic-lock”,“Lock”); .setHint(“openjpa.ReadLockLevel” “write”); .setParameter(“sym”,“ORCL”) .getResultList();

2007 JavaOneSM Conference | Session TS-4568 | 18 Pessimistic Transactions

• Optimistic concurrency is built into JPA, but no support for pessimistic locking is specified • Will likely be addressed in a future JPA release • All credible JPA implementations support pessimistic locks in some way or another • No completely portable way to pessimistically lock, but many provide query hints like those shown in previous slides • EntityManager lock() method can be used with optimistic locking, and error handling

2007 JavaOneSM Conference | Session TS-4568 | 19 Java DataBase Connectivity (JDBC™) Connection Settings

• Resource-level JDBC technology settings are vendors responsibility • Need to specify the four basic JDBC technology properties to obtain driver connections • Driver class, URL, username, password • The property keys will be different, but the values for a given JDBC technology data source will be the same for all vendors • Used when not in a container, or when managed data sources are not available or not desired

2007 JavaOneSM Conference | Session TS-4568 | 20 JDBC Technology Connection Settings

...

2007 JavaOneSM Conference | Session TS-4568 | 21 JDBC Technology Connection Settings

... ...

2007 JavaOneSM Conference | Session TS-4568 | 22 DDL Generation

• Standard enables it but does not currently dictate that providers support it • Mapping metadata specifies how DDL should be generated • Vendors may offer differing levels of support, including: • Generating DDL to a file only • Generating and executing DDL in DB • Dropping existing tables before creating new ones

2007 JavaOneSM Conference | Session TS-4568 | 23 DDL Generation

... ...

2007 JavaOneSM Conference | Session TS-4568 | 24 Database Platform

• No standard way to define the database platform being used at the back end • If provider knows the database then it can: • Generate corresponding SQL • Make use of db-specific features and types • Make adjustments for db-specific constraints and limitations • Implementations usually automatically discover database platform

2007 JavaOneSM Conference | Session TS-4568 | 25 Database Platform

... ...

2007 JavaOneSM Conference | Session TS-4568 | 26 Logging

• Users want to control over logging, but vendors use different logging APIs • Can usually configure to use one of the well- known logging APIs • java.util.logging, , etc. • Common requirement is to configure the logging level to show the generated SQL

2007 JavaOneSM Conference | Session TS-4568 | 27 Logging

... ...

2007 JavaOneSM Conference | Session TS-4568 | 28 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 29 Casting to Implementation Artifacts • Cast specification-defined interface to a vendor implementation type

public Employee pessimisticRead1(int id) { Employee emp = em.find(Employee.class, id); UnitOfWork uow = (TopLinkEntityManager) em.getUnitOfWork(); uow.refreshAndLockObject(emp, LOCK); return emp; }

2007 JavaOneSM Conference | Session TS-4568 | 30 Casting to Implementation Artifacts public Employee pessimisticRead2(int id) { Query q = em.createQuery( “SELECT e FROM Employee e “ + “WHERE e.id = :e_id”); q.setParameter(“e_id”, id); ((ObjectLevelReadQuery) ((TopLinkQuery)q.getDatabaseQuery())) .acquireLocks(); return q.getSingleResult(); }

2007 JavaOneSM Conference | Session TS-4568 | 31 Customization • Customization opens the door to any amount of twiddling • Can change or set additional vendor metadata • Customization class has compile-time dependencies, but limits the scope of them • Convenient place to stash vendor-specific feature code—if you change providers you know exactly where to look first • Write “default” code, if possible, so that even if the vendor code is not present the application will still work

2007 JavaOneSM Conference | Session TS-4568 | 32 Customization Using Properties

... ...

2007 JavaOneSM Conference | Session TS-4568 | 33 Customization Using Properties public class MySessionCustomizer implements SessionCustomizer {

public void customize(Session session) { session.setProfiler(new PerformanceProfiler()); } } public class MyDescriptorCustomizer implements DescriptorCustomizer {

public void customize(ClassDescriptor desc) { desc.disableCacheHits(); } }

2007 JavaOneSM Conference | Session TS-4568 | 34 Customizing Queries • May have lots of pre-existing queries in proprietary vendor query format • May want to access functionality in a custom or vendor-specific query language • Once they are added to the vendor EntityManager then they are accessible as normal JPA named queries • Can migrate them to JPQL or port them to a different vendor when/as required

2007 JavaOneSM Conference | Session TS-4568 | 35 Customizing a Query public class MySessionCustomizer implements SessionCustomizer {

public void customize(Session session) { DatabaseQuery query = session.getQuery(“Employee.findAll”); StoredProcedureCall call = new StoredProcedureCall(); call.setProcedureName("Read_All_Employees"); query.setCall(call); } }

2007 JavaOneSM Conference | Session TS-4568 | 36 Customizing a Query In entity code @Entity @NamedQuery(name="Employee.findAll", query="SELECT e FROM Employee e") public class Employee { ... }

In component code: ... return em.createNamedQuery("Employee.findAll") .getResultList(); ...

2007 JavaOneSM Conference | Session TS-4568 | 37 Vendor Annotations import javax.persistence.Entity; import oracle.toplink.annotations.Cache; import org.apache.openjpa.persistence.DataCache;

@Entity @Cache(disable-hits=TRUE) // TopLink annotation @DataCache(enabled=false) // OpenJPA annotation public class Employee { ... }

2007 JavaOneSM Conference | Session TS-4568 | 38 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 39 PK With Relationship

• Sometimes in the data model the primary key includes one or more foreign key columns • In the object model this means the identifier includes the identifier of a related entity • Relationship must exist when the entity is first created • Relationship may not change over the lifetime of the entity

2007 JavaOneSM Conference | Session TS-4568 | 40 PK With Relationship

• Each department may have many projects, but they must all have different names • Many projects may have the same name, but only if they belong to different departments

DEPT PROJECT PK ID PK NAME PK,FK DEPT_ID

2007 JavaOneSM Conference | Session TS-4568 | 41 PK With Relationship

/* Compound PK class */ public class ProjectId implements Serializable { int deptId; String name;

public ProjectId() {}

public ProjectId(int deptId, String name) { this.deptId = deptId; this.name = name; }

2007 JavaOneSM Conference | Session TS-4568 | 42 PK With Relationship

/* PK class (cont’d) */ public int getDeptId() { return deptId; } public String getName() { return name; }

public boolean equals(Object o) { return ((o instanceof ProjectId) && name.equals(((ProjectId)o).getName()) && deptId == ((ProjectId)o).getDeptId()); } public int hashCode() { return name.hashCode() + deptId; } }

2007 JavaOneSM Conference | Session TS-4568 | 43 PK With Relationship

/* The Project entity class */ @Entity @IdClass(ProjectId.class) public class Project { @Column(name="DEPT_ID", Do we make the Id insertable="false", mapping (@Column) read- updatable="false") only or the relationship (@JoinColumn) mapping? @Id private int deptId; @Id private String name;

@ManyToOne @JoinColumn(name="DEPT_ID") private Department department; ... }

2007 JavaOneSM Conference | Session TS-4568 | 44 PK With Relationship

• Depends on: • The vendor • How you use the entity • Some vendors support one or the other, or both • If you set the relationship when creating a Project and persist it without filling in the dept id then you might make the dept id read-only • If you set the dept id and then persist the Project then you might make the relationship read-only

2007 JavaOneSM Conference | Session TS-4568 | 45 Agenda

Background and Status The Portability Struggle Built-in Strategies Other Strategies Voice of Warning (A Case Study) Review and Summary

2007 JavaOneSM Conference | Session TS-4568 | 46 Review

• Persistence properties and query hints normally offer compile-time and runtime portability • Class casts introduce compile time and runtime dependencies • Vendor annotations introduce compile-time dependencies • Customization provides a “pluggable” dependency that can be easily removed • All of these may and often will result in subtle runtime dependencies

2007 JavaOneSM Conference | Session TS-4568 | 47 Summary

• No spec can or ever will offer everything to everyone • JPA must (and does) provide ways for vendors to add value and support features for their users • Vendors may also use other approaches to make features available • Developers should be aware of non-portable features, and consequences of using them • Spec is well-positioned to add new features as requested by the community

2007 JavaOneSM Conference | Session TS-4568 | 48 For More Information

• Technical Sessions • TS-4902: Java Persistence API: Best Practices & Tips Friday, 10:50AM • Resources • http://otn.oracle.com/jpa • Books • Pro EJB 3: Java Persistence API

Mike Keith & Merrick Schincariol (Foreword by Rod Johnson)

2007 JavaOneSM Conference | Session TS-4568 | 49 Q&A

2007 JavaOneSM Conference | Session TS-4568 | 50 Java™ Persistence API: Portability Do’s and Don’ts Mike Keith Oracle Corp. http://otn.oracle.com/jpa

TS-4568

2007 JavaOneSM Conference | Session TS-4568 |