-
Notifications
You must be signed in to change notification settings - Fork 1
Home
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.
Example:
class MyClass extends Something with SimpleEntityManagerFactory with ThreadLocalEntityManager { def getPersistenceUnitName = "mip" }
A XML file collects all the used HQL statements.
Current Scala persistence implementations are trying to provide type safe SQL/HQL statements as classes and objects. I don’t think that this is the best way.
- SQL/HQL syntax is quite complex. IMHO it will not be possible to rewrite the whole functionality (especially taking into account SQL enhancements like PostGIS or db vendor dialects)
- I have learned that it can make sense to change a SQL/JPQL statement in production (add redundancy tables etc.)
- Nevertheless, type safe SQL/JPQL parameter are important
- JPA and JPA2.0 are widely adopted and used (field proven implementations) java standards
<filter> <!-- simple JPQL query with one parameter--> <query id="UserFromName" jpql="select u from User u where u.name like ?1"/> <!-- simple native SQL query with two parameter--> <query id="DistancePointFromTextToLocID" jpql="select distance(pointfromtext(?1),lp.geometry) from location_point as lp where lp.loc_id=?2"/> <!-- JPQL query with one parameter and filer class. Maps N to name --> <query id="FindObjectItemFromNameWithFilter" alias="oi" jpql="oi.nameTxt like :N"> <filterClass class="com.jpaextension.test.NameFilter"> <binding var="N" attribute="name"/> </filterClass> </query> <!-- JPQL query with relation fetch statements and query annotations --> <query id="fetchFilter" alias="c" annotation="myAnno1 myAnno2"> <fetch property="owner"/> <fetch property="sparePart" joinType="left"/> </query> </filter>
The above defined 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.
val filter: NameFilter = newFilterInstance(QueryId("FindObjectItemFromNameWithFilter")) filter.name = "%Test%" var i = 0 forQueryResults { oi: ObjectItem => i = i + 1 } withQuery (filter) i must_== 10
The fetch tag allows the preload of (lazy) relations. In case of fetchFilter the relations owner and sparePart are fetched while loading the data from DB.
For the design of persistence layers it is useful to provide some query annotations (as a list of simple text). myAnno1 is an example. Annotations can be retrieved using a filer object.
Sometimes several queries contain a common part. This can be put as a constant snippet to JPAExtension.xml.
withNoTrx { val user: User = oneResultQuery withQuery (QueryId("UserFromName"), "Lionel") user }
withNoTrx { forQueryResults { u: User => userIDs.add(u.getId) userNames.add(u.getName) } withQuery (QueryId("UserFromName"), "%" + name + "%") }
withTrxAndCommit { findAndApply(id ) { u:User => remove(u) } }
withTrxAndCommit { oneResultQueryAndApply { d: Double => eStatRet.setDistance(d) } withNativeQuery (QueryId("DistancePointFromTextToLocID"), postGISPoint, user.getUsersLocation.getId) }
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.
@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) } } } } }
The XML snippet defines that com.jpaextension.test.data.SomeFilter will contain the binding parameter NT and CID for query MyOIQuery.
<query id="MyOIQuery" alias="oi" jpql="oi.creatorId=:CID and oi.nameTxt=:NT"> <filterClass class="com.jpaextension.test.data.SomeFilter"> <binding var="CID" attribute="creatorId"/> <binding var="NT" attribute="nameTxt"/> </filterClass> </query>
The following code creates a Filter Object myFilter, sets the binding parameter and executes the query.
withNoTrx { val myFilter: SomeFilter = newFilterInstance(QueryId("MyOIQuery")) myFilter.creatorId = BigInteger.valueOf(815) myFilter.nameTxt = "Test1" val result = createFilterQuery[ObjectItem](myFilter).getResultList result.size must_== 1 }