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:
- Constructor Arguments with JPA-Annotations
- Relations with Scala Collections and JPA
- Scala Entity and JPAExtension Examples
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) } } } } }
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
please check out the Specs tests here. Additionally, the pom.xml should show the required imports.