Message-ID: <1281285620.2053.1369273797842.JavaMail.email@example.com> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_2052_1321250800.1369273797842" ------=_Part_2052_1321250800.1369273797842 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) Hib= ernate=C2=A0 component of the grepo framework.It's not supposed to be= a complete reference manual - the goal is to show a basic usage and config= uration scenario of grepo's gquery component (using hibernate). If you have= problems understanding parts of this guide or the framework in general or = if you have any suggestions, good ideas or if you have found potential bugs= please let us know. So let's get started!
This is the gett= ing started guide for the Generic Query (gquery) Hibernate=C2=A0 = component of the grepo framework version 1.0.x.
You can find the latest version of this guide here.
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 Hibernate to one Java entity (demo.domai= n.User). Note that the object relational mapping is done using standar= d Hibernate mechanisms and is not grepo specific. The mapping can be found = in src/main/resources/META-INF/hibernate/User.hbm.xml. The USE= RS table contains the following columns:
not null, primary key
not null, unique
In order to use the gquery component with Hibernate you need the followi= ng grepo artifacts (jars) in your project's classpath:
Somewhere in your Spring application context (xml) you have to import th= e default Hibernate 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 Hibernate session fact= ory. This configuration is "standard" Spring/Hibernate and is not= grepo specific. In the demo project the hsql datasource and session factor= y are configured in src/main/resources/META-INF/spring/db-environment.x= ml.
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
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.hibernate.repository.ReadWriteHibernateRepository. = For a read-only repository we would exend from org.codehaus.grepo.query= .hibernate.repository.ReadOnlyHibernateRepository instead. The first g= eneric type is the Java entity (User) and the second one is the ty= pe for the primary key property 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 HQL or SQL). In our application we migh= t want to load a user from database via username property. Therefo= re we would add the following method to our UserRepository interfa= ce:
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 HQL query to be executed when the method gets invoked. We= can also execute SQL queries:
Here we have to use grepo's HibernateQueryOptions annotation to= tell the framework that an instance of User has to be returned.= p>
We could also use Hibernate's named-parameter style for placeholders in = our query (instead of the JDBC style which uses question marks as placehold= ers):
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.ExecutorFindingStrategy which is responsible fo= r finding the appropriate executor for a given generic method. In its defau= lt configuration grepo uses org.codehaus.grepo.query.commons.executor.Q= ueryExecutorFindingStrategyImpl. This implementation uses a org.co= dehaus.grepo.query.commons.executor.QueryExecutorNamingStrategy which = is responsible to retrieve an executor name for a given method. Furthermore= the QueryExecutorFindingStrategyImpl has a registry (basically a = Map) which maps executor names to executor classes. The org.co= dehaus.grepo.query.commons.executor.QueryExecutorNamingStrategyImpl (w= hich is the one grepo uses in its basic configuration) resolves executor na= mes 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, scroll, iterate, delete or update<= /em> this rule will 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 Hibernate's concept of named queries to achieve that. This would make y= our repository methods even easier:
In our mapping file (src/main/resources/META-INF/hibernate/User.hbm.= xml) we would define the the HQL 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 Hibe= rnate session factory). The answer is conventions. Grepo uses a org.cod= ehaus.grepo.query.commons.executor.QueryExecutorFactory which is respo= nsible for creating QueryExecutor instancess. Grepo's default impl= ementation is org.codehaus.grepo.query.commons.executor.QueryExecutorFa= ctoryImpl which uses a org.codehaus.grepo.query.commons.naming.Que= ryNamingStrategy. You could write your own implementation and tell gre= po to use that strategy instead. Grepo's default implementation is org.= codehaus.grepo.query.commons.naming.QueryNamingStrategyImpl which reso= lves 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, scroll, iterate, delete or update th= is rule will be applied. The example above shows how the query for the = getByUsername method was resolved to "demo.domain.User.ByUser= name". 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.hibernate.generator.HibernateQueryGenerator interface. A sim= ple implementation which generates a HQL 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 HQL you would just use org.codehaus.grepo.query.hibernate.g= enerator.AbstractHibernateNativeQueryGenerator as the base class for y= our generator. Furthermore you can also use the Hibernate Criteria API like= this:
The method would be defined in the UserRepository as follows:= p>
Hibernate offers paging functionality which can be used with gr= epo's MaxResults and FirstResult annotations like this:= p>
It's also possible to use the firstResult and maxResults properties of t= he 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:
Hibernate also offers a similiar feature known as result transformat= ion. You can use this feature using grepo's HibernateQueryOption= em> annotation by configuring the resultTransformer property accor= dingly.
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/Hibernate. However grepo also opti= onally supports transaction handling using spring's transaction template (s= ee abstractRepository above). If you don't want grepo to handle tr= ansactions you just do not configure the transactionTemplate prope= rty. Additionally you can configure the readOnlyTransactionTemplate property. Doing so grepo will use the read-only template for executing re= ad-only operations. If no read-only template is defined, then grepo will us= e the transactionTemplate (if configured) for both read- and write= -operations. Here is an example of the abstractRepository bean wit= h 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_2052_1321250800.1369273797842--