AccessPlatform 3.3 and JPA 2.1

We will soon be releasing AccessPlatform 3.3. This is coming very soon after 3.2, and the reason for this is that it is simply AccessPlatform 3.2 plus full support for JPA 2.1 (i.e an upgraded datanucleus-api-jpa plugin). From that point both of these “versions” of AccessPlatform will be maintained for a period of time. So what is provided in JPA 2.1 ?

Stored Procedures

You can execute RDBMS Stored Procedures using the JPA API. This API should give you quite complete control over execution of any stored procedure, setting of IN/OUT/INOUT parameters and obtaining result set(s). To give an example

StoredProcedureQuery spq = 
em.createStoredProcedureQuery(procName);
spq.registerStoredProcedureParameter("PARAM1",
Integer.class, ParameterMode.OUT);
boolean val = spq.execute();
Object paramVal = spq.getOutputParameterValue("PARAM1");

So here we have a stored proc that we register an Integer output parameter, and retrieve the value when we execute it. This is just one mode of operation, and you can see more usages in the documentation.

Entity Graphs

JPA has only had an equivalent of the JDO “default fetch group” since its inception. In this release it finally gets some degree of control over what fields are fetched when fetching an object from the datastore. To give an example, we have a class Person and want to pull in a field “bestFriend” under some circumstances but not by default. We define a named EntityGraph in metadata


@Entity
@NamedEntityGraph(name="includeFriend", attributeNodes= {@NamedAttributeNode("bestFriend")})
public class Person
{
@OneToOne;
Person bestFriend;

...
}

and now we want to use this entity graph when loading an object of this type. We do this as follows.

EntityGraph friendGraph = em.getEntityGraph("includeFriend");
Properties props = new Properties();
props.put("javax.persistence.loadgraph", friendGraph);
MyClass myObj = em.find(Person.class, id, props);

So we retrieved the EntityGraph, and then used it in the find method. Equally we could have used it in a Query. You can read more about this topic in the documentation.

Schema Generation

JPA 2.1 allows generation of the schema as an up front task, or via Persistence.generateSchema(). You can specify this by making use of persistence properties, for example javax.persistence.schema-generation.database.action set to create. See the available persistence properties for details.

Foreign-Keys and Indexes

JPA 2.1 adds on the ability to specify RDBMS schema foreign-keys and indexes, for use during schema generation. By default a JPA implementation is free to generate whatever foreign-keys it decides are appropriate, but this ability allows a user to override this and control what is generated.


@OneToOne
@JoinColumn(name="BESTFRIEND_ID", foreignKey=
@ForeignKey(name="BESTFRIEND_FK", foreignKeyDefinition=
"FOREIGN KEY (BESTFRIEND_ID) REFERENCES PERSON (PERSON_ID) ]"))
Person bestFriend;

which will create a foreign key called “BESTFRIEND_FK” for this purposes. Similarly we can define indexes on a table of a class.

@Entity
@Table(indexes={@Index(name="FIRSTNAME_IDX", columnList="FIRST_NAME")})
public class Person
{
@Column(name="FIRST_NAME")
String firstName;

...
}

so the firstName field is now indexed. You can read more about this topic in the documentation.

Criteria UPDATE/DELETE queries

Whilst the JPA Criteria API is overengineered and verbose it now has the ability to generate UPDATE and DELETE queries. For example


CriteriaUpdate crit = qb.createCriteriaUpdate(Person.class);
Root candidate = crit.from(Person.class);
candidate.alias("p");
crit.set(candidate.get(Person_.firstName), "Freddie");
Predicate teamName = qb.equal(candidate.get(Person.firstName), "Fred");
crit.where(teamName);
Query q = em.createQuery(crit);
int num = q.executeUpdate();


which will create the JPQL “UPDATE Person p SET p.firstName = ‘Freddie’ WHERE p.firstName = ‘Fred'”. You can do similar things for DELETE queries. You can read more about this topic in the documentation

Attribute Converters

By default a JPA implementation will persist a field in a datastore column of its chosen type. You can now override this to use a converter, performing the conversion from the field type to the datastore type in your converter class. The example we use in the documentation is where we have a field in our class of type URL and want to persist this as a String-type in the datastore (VARCHAR, CHAR etc).


public class URLStringConverter implements AttributeConverter
{
public URL convertToEntityAttribute(String str)
{
if (str == null)
{
return null;
}

URL url = null;
try
{
url = new java.net.URL(str.trim());
}
catch (MalformedURLException mue)
{
throw new IllegalStateException("Error converting the URL", mue);
}
return url;
}

public String convertToDatabaseColumn(URL url)
{
return url != null ? url.toString() : null;
}
}

and then in our class that has a URL field we mark the field to use this converter


@Basic
@Convert(converter=URLStringConverter.class)
URL url;

You can read more about this topic in the documentation.

JPQL FROM “ON” clauses

When joining in JPQL previously we could not add additional constraints on the join. You can now do this using the “ON” clause.


List result = em.createQuery(
"SELECT Object(A) FROM Account A LEFT OUTER JOIN A.login L ON L.userName = 'fred'").getResultList();

JPQL “FUNCTION”

No matter what features you put in a query language some people will always want to make use of SQL functions specific to a particular datastore. With JPQL you can now do this using the FUNCTION keyword, like this


Query q = em.createQuery(
"SELECT p FROM Person p WHERE FUNCTION('UPPER', p.firstName) = 'FRED'");

As you can see, JPA 2.1 is a minor iteration on JPA, and you can now benefit from all of these features in DataNucleus AccessPlatform 3.3

Advertisements
This entry was posted in AccessPlatform, JPA. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s