JPA For Scala

JPAExtension (JPA for Scala, ORM for Scala) should:

  • be fully JPA 2.0 compliant Persistence Layer and Object Relational Mapper (ORM) for Scala
  • perfectly replace the Java API with Scala Collections and other niceties
  • support Transaction Scope Wrappers with Scalas Functional Programming abilities

JPAExtension is hosted on Github

Related Artikel are:

What is JPA

The Java Persistence API is a POJO persistence API for object/relational mapping. It contains a full object/relational mapping specification supporting the use of Java language metadata annotations and/or XML descriptors to define the mapping between Java objects and a relational database. It supports a rich, SQL-like query language (which is a significant extension upon EJB QL) for both static and dynamic queries. It also supports the use of pluggable persistence providers.
(this is taken from here)

Advantages:

  • Pluggable Implementations
  • Widely used standard
  • Widely available experience
  • Supported by application server vendors

Three major JPA 2.0 implementations:

Entity Manager and Entity Manager Factory

The framework suports custom EntityManagerFactory implementations. To simplify usage two Traits can be used.

SimpleEntityManagerFactory provides a non JNDI environment EM factory. Method getPersistenceUnitName has to be implemented to provide the persistence unit name as defined in persistence.xml.

ThreadLocalEntityManager provides one Entity Manager instance per Thread.

Mixing in Traits:

class MyClass extends Something
    with SimpleEntityManagerFactory
    with ThreadLocalEntityManager {
 /*
  * using persistence unit called "mip" here
 */
 def getPersistenceUnitName = "mip"
 . . .
}

Queries

Query definitions are externalized to an xml file.

  • I have learned that it can make sense to change a SQL/JPQL statement in production (add redundancy tables or change the statements itself etc.)
  • the fetch tag allows to preload of (lazy) relations
  • queries can have named text annotations that can be retrieved at runtime
  • Sometimes several queries contain some common parts. They can be combined as snippets.
  • Allows the typesafe definition of JPQL/SQL query parameter holder objects, the filter objects

examples for JPAExtension.XML

simple JPQL query with one parameter:



simple native PostGIS SQL query with two parameter:



JPQL query with one parameter and filer class. Maps N to name:

  
    
      
    
  

JPQL query with relation fetch statements and query annotations:

  
	
	
  

Execute Query with Filter Class:

The query with the ID FindObjectItemFromNameWithFilter can use the filter NameFilter for holding the binding attribute name. name will be used to replace N.
Since the query can return more than one result forQueryResults can be used to iterate over the result-set.

Filter definition:

class NameFilter {
  var name: String = _
}

Using Filter and executing query:

. . .
val filter: NameFilter = newFilterInstance(QueryId("FindObjectItemFromNameWithFilter"))
filter.name = "%Test%"

var i = 0
forQueryResults {
  oi: ObjectItem =>
    i = i + 1
} withQuery (filter)
i must_== 10
. . .

Transaction Scope Wrappers

Iterating over query results without transaction

withNoTrx {
 forQueryResults {
  u: User =>
   userIDs.add(u.getId)
   userNames.add(u.getName)
 } withQuery (QueryId("UserFromName"), "%" + name + "%")
}

Find one entity, remove it and commit the transaction

withTrxAndCommit {
 findAndApply(id ) {
   u:User => remove(u)
 }
}

Execute a native PostGIS SQL query and expect one result

withTrxAndCommit {
 oneResultQueryAndApply {
  d: Double =>
   eStatRet.setDistance(d)
  } withNativeQuery (QueryId("DistancePointFromTextToLocID"), postGISPoint, user.getUsersLocation.getId)
}

Server Side Usage Example

These examples are using a JAX-RS standard implementation from SUN called Jersey.
exceptionWrapper and checkAccessRights are used to generate WebApplicationExceptions and to check the access rights based on HTTP-session credentials.
The code updates the UserInfo entity with merge and commits the transaction.

 @PUT
 @Path("UserInfo/{uid}")
 def updateUserInfo(@PathParam("uid") uid: String, eui: EUserInfo): EUserInfo = {
   exceptionWrapper {
     checkAccessRights {
       withTrxAndCommit {
         findAndApply(id(uid) ) {
           u:User =>
             val userInfoId = u.getUserInfo.getId
             val newUserInfo: UserInfo = eui.getUserInfo
             newUserInfo.setId(userInfoId)
             merge[UserInfo](newUserInfo)
         }
       }
     }
   }
 }

2 thoughts on “JPA For Scala

  1. Hello

    I’m a beginner in scala, maven and Java. i’ve tried to reproduce your example, but unforunatly i did not manage to get it to compile and run. so I have a question. Is it posible that you can mail me the examples you showed here i thin i have problems with teh correct imports and libraries. Im using netbeans 6.9.1. this would be a great help for me. thank you.
    Martin

  2. please check out the Specs tests here. Additionally, the pom.xml should show the required imports.