Message-ID: <969875886.1689.1369249439087.JavaMail.firstname.lastname@example.org> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_1688_1931988018.1369249439086" ------=_Part_1688_1931988018.1369249439086 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
This is the getting started guide for the Generic Query (gquery= ) Jpa component of the grepo framework. It's not supposed to be a = complete reference manual - the goal is to show a basic usage and configura= tion scenario of grepo's gquery component (using jpa). If you have problems= understanding parts of this guide or the framework in general or if you ha= ve any suggestions, good ideas or if you have found potential bugs please l= et us know. So let's get started!
This is the getting started guide for the Generic Query (gquery) Jp= a=C2=A0 component of the grepo framework version 1.0.x.
You can find the latest version of this guide=C2=A0here.
The demo project for this guide can be checked out from our SVN reposito= ry as follows:
The demo project is a maven project and we highly recommend that you use= maven to set up the project. If you don't want to use maven you can also s= et up the project manually. If you use maven and eclipse you can easily mak= e an eclipse project using the following command in the demo project's root= directory:
You can now import the project in your eclipse workspace.
After you have imported the project you should now be able to run the
Grepo uses the commons-logging library. If you set the logger level for = the package org.codehaus.grepo to TRACE in (src/test/= resources/log4j.xml) like this:
Grepo should print out information similar to this:
The teeny-weeny demo application consists of one database table (USE= RS) which is mapped using Jpa to one Java entity (demo.domain.User= ). Note that the object relational mapping is done using standard Jpa = mechanisms and is not grepo specific. The mapping can be found in src/m= ain/resources/META-INF/jpa/mapping.xml. The USERS table conta= ins the following columns:
not null, primary key
not null, unique
In order to use the gquery component with Jpa you need the following gre= po artifacts (jars) in your project's classpath:
Somewhere in your Spring application context (xml) you have to import th= e default Jpa configuration of the grepo gquery component.
In the demo project this is done in src/main/resources/META-INF/spri= ng/application-context.xml. Note that you may not need to import that = file if you decide to setup grepo with special/custom configuration - you c= ould for instance configure the required "grepo" beans d= irectly in your application context.
Furthermore you need to define a datasource and a Jpa entity manager fac= tory. This configuration is "standard" Spring/Jpa and is not grep= o specific. In the demo project the hsql datasource and entity manager fact= ory are configured in src/main/resources/META-INF/spring/db-environment= .xml.
The next step is to define a basic configuration for the data access lay= er. This configuration may look like this:
Here we define an abstract bean which will be used for all of o=
ur concrete repositories (DAOs). Its a good idea (although not required) to=
define an abstract bean because this makes configuration of concr=
ete repository beans simpler and furthermore you just have to modify the
That's it, you are now ready to build your data access layer using the g= repo framework!
Now its time to create the generic repository for the User enti= ty. For this we just have to define an empty interface (demo.repository= .UserRepository), which looks like:
Note that we want a read-write repository (this means that we want a rep= ository with basic CRUD operations) and thus have to extend from org.co= dehaus.grepo.query.jpa.repository.ReadWriteJpaRepository. For a read-o= nly repository we would exend from org.codehaus.grepo.query.jpa.repository.= ReadOnlyJpaRepository> instead. The first generic type is the Java entit= y (User) and the second one is the type for the primary key proper= ty of the entity (Long).
The next step is to configure a repository bean in our Spring applicatio= n context:
The userRepository bean uses the abstractRepository be= an as parent and thus inherits the basic configuration from the parent. We = have to set (al least) one property:
Finished! We can now inject our userRepository bean wherever we= need basic CRUD operations for the User entity.
We can now add various methods to our UserRepository interface = in order to execute queries (either JPQL or SQL). In our application we mig= ht want to load a user from database via username property. Theref= ore we would add the following method to our UserRepository interf= ace:
And thats it! We can now inject our userRepository bean and use= the getByUsername method to fetch User entities from dat= abase by username. As you can see we use grepo's GenericQuery<= /em> annotation to tell the framework that the method has to be executed (o= r handeled) dynamically (remember that we didn't have to provide and implem= entation of our UserRepository interface). The query prop= erty provides the JPQL query to be executed when the method gets invoked. W= e can also execute SQL queries:
Here we have to use grepo's JpaQueryOptions annotation to tell = the framework that an instance of User has to be returned.
We could also use Jpa named-parameter style for placeholders in our quer= y (instead of the JDBC style which uses question marks as placeholders):
Note that we also have to annotate the method's parameters with grepo's = Param annotation. This is necessary to associate method parameters= with named-parameters in the query. Even though using named-parameters req= uires a litte more configuration in your interface (because of the Para= m annotation), there are several reasons why someone would (and should= ) prefer named-paramter in queries:
The attentive reader may wonder how grepo can return the appropriate typ=
es. The getByUsername method returns an instance of User =
while findByUsernames returns a list of User entities. Th=
e answer is conventions. Grepo is configured with a set of org.codehaus=
.grepo.query.commons.executor.QueryExecutors. As the name implies a
So obviously grepo used the ListQueryExecutor for the findB= yUsernames and the GetQueryExecutor for the getByUsername= method. But how did grepo know which executor has to be used for whic= h method (Note that we didn't tell grepo which executor has to be used). Th= e answer is again conventions. The framework uses a org.codehaus.grepo.= query.commons.executor.QueryExecutorFindingStrategy which is responsib= le for finding the appropriate executor for a given generic method. In its = default configuration grepo uses org.codehaus.grepo.query.commons.execu= tor.QueryExecutorFindingStrategyImpl. This implementation uses a o= rg.codehaus.grepo.query.commons.executor.QueryExecutorNamingStrategy w= hich is responsible to retrieve an executor name for a given method. Furthe= rmore the QueryExecutorFindingStrategyImpl has a registry (basical= ly a Map) which maps executor names to executor classes. The o= rg.codehaus.grepo.query.commons.executor.QueryExecutorNamingStrategyImpl (which is the one grepo uses in its basic configuration) resolves execut= or names according to the following rules:
If the name of the method matches the pattern
then the executor name is the matching prefix. This means that if the me= thod starts with is, has, get, load, delete or update this rule wi= ll be applied.
If the method name does not match the pattern above, then null will be returned, meanin= g that the strategy didn't find the appropriate executor name for this meth= od.
Feel free to provide your own implementation if desired. Note also that = it is always possible to write a custom QueryExecutor without grep= o being aware of that implementation. So you can use grepo's default config= uration and write your own QueryExecutor and tell it to use this e= xecutor like this:
Using this approach is straight forward, because you tell grepo what exe= cutor has to be used and thus the framework doesn't use the QueryExecut= orNamingStrategy at all. That's good if you have only a few methods wh= ich require a special/custom executor. If you want to use your custom execu= tors more frequently then it's propably better to configure the framework a= ccordingly.
You may not want to have the queries directly in your Java code. Grepo u= ses Jpa's concept of named queries to achieve that. This would make your re= pository methods even easier:
In our mapping file (src/main/resources/META-INF/jpa/mapping.hbml.xm= l) we would define the the JPQL query like this:
An appropriate SQL query would look like:
You may now wonder how grepo is able to find the correct query to execut= e (you will most likely have several named queries defined within your Jpa = entity manager factory). The answer is conventions. Grepo uses a org.co= dehaus.grepo.query.commons.executor.QueryExecutorFactory which is resp= onsible for creating QueryExecutor instancess. Grepo's default imp= lementation is org.codehaus.grepo.query.commons.executor.QueryExecutorF= actoryImpl which uses a org.codehaus.grepo.query.commons.naming.Qu= eryNamingStrategy. You could write your own implementation and tell gr= epo to use that strategy instead. Grepo's default implementation is org= .codehaus.grepo.query.commons.naming.QueryNamingStrategyImpl which res= olves query names for generic methods according to the following rules:
If the queryName prop= erty is set for the GenericQuery annotation, then this value is used as the query name. For instan= ce:
If the name of the method matches the pattern
then the query name is composed of the fully qualified entity class name= and the method name (with removed prefix). This means that if he method st= arts with is, has, get, load, delete or update this rule will be a= pplied. The example above shows how the query for the getByUsername method was resolved to "demo.domain.User.ByUsername". = Note that the matched prefix is removed.
If the name of the method does not match the pattern above, then= the query name is composed of the fully qualified entity class name and th= e complete method name (without removed prefix).
So far we have only used static queries. But you may also want to genera= te your queries dynamically depending on the given method (input) parameter= s. In our application we may want a method which finds users via their = firstname and/or lastname. For this we can either just implem= ent the method ourselves (meaning not annotating the method with Generi= cQuery) or we could write an implementation of the org.codehaus.gr= epo.query.jpa.generator.JpaQueryGenerator interface. A simple implemen= tation which generates a JPQL query looks like:
In our UserRepository we would define a method like this:
Note that it is required to generate queries with named-parameter style = (as JDBC style does not work). If you want to generate a SQL (native) query= instead of JPQL you would just use org.codehaus.grepo.query.jpa.genera= tor.AbstractJpaNativeQueryGenerator as the base class for your generat= or.
Jpa offers paging functionality which can be used with grepo's = MaxResults and FirstResult annotations like this:
It's also possible to use the firstResult and maxResults properties of the GenericQuery annotation.
The framework supports result conversion functionality. For this grepo u= ses implementations of the org.codehaus.grepo.core.converter.ResultConv= erter interface. ResultConverters can be used to convert the = result of a query invocation and may be configured for methods using grepo'= s GenericQuery annotation, like this:
Furthermore grepo supports so called implicit result conversion, which m= eans that in some cases (if necessary) the result will be converted automat= ically (without configuration). The framework uses a org.codehaus.grepo= .core.converter.ResultConverterFindingService. Grepo's default impleme= ntation org.codehaus.grepo.core.converter.ResultConverterFindingService= Impl uses a registry (basically a Map) to map (return) ty= pes to ResultConverter classes. The ResultConverterFindin= gService checks if conversion is required (for instance if query resul= t is not compatible with method return type) and uses the registry= in order to retrieve the appropriate converter to use. In its default conf= iguration grepo knows the following ResultConverters:
Suppose we need functionality for our demo application wich allows to re= gister new users. As we have seen the email property is unique and= thus must not already exist in the database. We could use the following me= thod so we can check for existing email-addresses:
Note that the query returns 0 or 1 (because email<= /em> is unique) and the method's return type is boolean. Executing= this method (and having grepo logger level set to TRACE) the foll= owing will be logged:
The framework supports result validation functionality. For this grepo u= ses implementations of the org.codehaus.grepo.core.validator.ResultVali= dator interface. ResultValidators can be used to validate the= result of a method invocation. Note that result validation is performed af= ter result conversion. ResultValidators can be configured for meth= ods using grepo's GenericQuery annotation like this:
You configure transaction handling for your repository objects (DAOs) as= you would do normally with plain Spring/Jpa. However grepo also optionally= supports transaction handling using spring's transaction template (see abstractRepository above). If you don't want grepo to handle transact= ions you just do not configure the transactionTemplate property. A= dditionally you can configure the readOnlyTransactionTemplate prop= erty. Doing so grepo will use the read-only template for executing read-onl= y operations. If no read-only template is defined, then grepo will use the = transactionTemplate (if configured) for both read- and write-opera= tions. Here is an example of the abstractRepository bean with both= templates defined:
The grepo framework was designed around the convention over configuration paradigm. You configure the grep= o framework with your guidelines (if the default configuration does not mee= t your needs) for your data access layer and grepo will then apply those ru= les transparently. For instance, we have seen that grepo can guarantee that= all methods which execute "list-queries" have to start = with the prefix "list" and also have to return an instan= ce of java.util.List. If you want to break the rules you could for= instance configure a method as follows:
Note that the method name does not meet the conventions. The method star= ts with "get" but actually a "list-query&q= uot; is required because of the method's return type (java.util.List). Here you can see the power of the convention over configuration paradi= gm and grepo in general. Breaking the rules is still possible but you have = to know what you're doing and furthermore have additional configuration ove= rhead.------=_Part_1688_1931988018.1369249439086--