Hey Rick, this flew by and I didn't take a look at it. Now that I'm
starting to get into JPA stuff I'll definitely read this over and let
you know.
-warner
On Apr 24, 2007, at 3:36 PM, Rick Hightower wrote:
Using the JPA Generic DAOIntroduction
This document describes how to use Crank's JPA Generic DAO support.
Now that a few people are using this. I thought it was time to do a
quick write up. Seehttp://code.google.com/p/krank/ for more details
(view the Wiki).
See this online at: http://jroller.com/page/RickHigh?
entry=using_the_jpa_generic_dao
Features of JPA Generic DAO covered in this document
JPA support for CRUD operations Create, Read, Update, Delete
Support for defining no-code finder methods
Support for Criteria API/DSL
Support for easy to use finder methods
Getting Started with JPA Generic DAO
The DAO support is based on the Spring JPA support . There is some
talk on the Crank team for supporting similar features for non-
Spring developers, but for now both of you will have to use Spring
to use this DAO support.
Everything that applies to
`org.springframework.orm.jpa.support.JpaDaoSupport` also applies to
Cranks DAO support (`org.crank.crud.GenericDaoJpa`) as it
subclasses `JpaDaoSupport` from Spring. Note that all of our DAO
objects implement `org.crank.crud.GenericDao`.
Steps to using Crank JPA DAO support
Setup Spring environment
Configure DAO object
Start using the DAO
Step 1 Setup Spring environment
Here is how the example projects sets up the Spring environment:
Main context
"http://www.springframework.org/schema/beans" xmlns:xsi="http://
www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://
www.springframework.org/schema/beans http://www.springframework.org/
schema/beans/spring-beans-2.0.xsd"> <import
resource="classpath:spring/dao-beans.xml" /> <import
resource="classpath:spring/resource-defs.xml" />
Resource context
"http://www.springframework.org/schema/beans" xmlns:xsi="http://
www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://
www.springframework.org/schema/beans http://www.springframework.org/
schema/beans/spring-beans-2.0.xsd"> "entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
"persistenceUnitName" value="crank-crud-test" />
"transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
"entityManagerFactory" ref="entityManagerFactory" />
See Spring JPA support for more details.
Of course you will have to setup a persistence.xml file as well
refer to JPA documents for how to setup a persistence.xml file. For
this project, the persistence.xml file is as follows:
/META-INF/persistence.xml
"1.0" encoding="UTF-8"?> "http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://
java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
"crank-crud-test" transaction-type="RESOURCE_LOCAL">
org.hibernate.ejb.HibernatePersistence
org.crank.crud.test.model.Employee
"hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /
> "hibernate.connection.url" value="jdbc:mysql://localhost:3306/
crank-crud?autoReconnect=true" /> "hibernate.connection.username"
value="crank" /> "hibernate.connection.password"
value="sleeplessintucson" /> "hibernate.dialect"
value="org.hibernate.dialect.MySQLDialect" />
"hibernate.cache.provider_class"
value="org.hibernate.cache.HashtableCacheProvider" />
"hibernate.show_sql" value="true" /> "hibernate.hbm2ddl.auto"
value="update" />
Step 2 Configure DAO object
In order to use the DAO object, you must configure it. The DAO
object needs to know which entity it is managing; thus, you need to
pass it an Entity class as follows:
DAO Beans context file
"genericDao" class="org.crank.crud.GenericDaoJpa"> "type"
value="org.crank.crud.test.model.Employee"/> "entityManagerFactory"
ref="entityManagerFactory" />
Next inject the genericDao through a setter method as follows
(using normal Spring injections):
private GenericDaoLong> genericDao; public void setGenericDao
( final GenericDaoLong> baseJpaDao ) { this.genericDao = baseJpaDao; }
Notice that we define the genericDao as a DAO that works with
Employees who have a PK that is a Long.
Step 3 Start using the DAO
Once you have the DAO defined and injected, you can start using it.
You can read objects by id:
Employee employee = (Employee) genericDao.read( 1L );
You can create new objects:
genericDao.create(new Employee("Rick", "Hightower"));
You can update objects (not needed if in same transaction):
Employee employee = (Employee) genericDao.read( 1L ); ... //Present
to user employee.setFirstName("Rick"); genericDao.update( employee );
JPA does dirty checking so the update is not needed if run in the
same transaction.
You can also delete objects as follows:
You can delete an object as well:
Employee employee = (Employee) genericDao.read( 1L );
genericDao.delete( employee.getId() );
There are helper methods for finding objects as follows:
Map<String, Object> params = new HashMap<String, Object>();
params.put("firstName", "Rick"); List employees = genericDao.find
( params, new String[] { "firstName" });
The above finds and employee with the first name of Rick. If there
are more than one employees named Rick, the list will be ordered by
firstName.
You can also search by related objects. Below we search for
employees who are in the department named Engineering (where
Employee has an related entity called Department).
List employees = genericDao.find("department.name", "Engineering");
The above is shorthand for the following:
import static org.crank.crud.criteria.Example.*; import static
org.crank.crud.criteria.Comparison.*; import static
org.crank.crud.criteria.Group.*; ... ... List employees =
genericDao.find(eq("department.name", "Engineering"));
Notice the use of the `eq` method. We provided a Criteria DSL where
you can any number of criterion.
Here are some examples of using the Criteria DSL
employees = genericDao.find( eq("department.name", "Engineering"),
or( startsLike("firstName", "Rick"),like("firstName", "Ri")) );
employees = genericDao.find( or ( eq("department.name",
"Engineering"), like("firstName", "Ri") ) ); employees =
genericDao.find( in("age", 1, 2, 3, 4, 5, 6, 40) );
The Criteria DSL has all of the operators that you expect, e.g.,
and, or, eq, ne, gt, ge, etc.
The Criteria DSL even has support for Query by Example (QBE):
Employee employee = new Employee(); employee.setActive(true);
employee.setAge(40); employee.setFirstName("Rick");
employee.setLastName("Rick"); List employees = genericDao.find( like
(employee).excludeProperty("lastName"));
You can even refer to nested QBE objects:
employee = new Employee(); employee.setFirstName("Ric");
employee.setAge(0); employee.setActive(true); Department department
= new Department(); department.setName("Eng");
employee.setDepartment(department); employees = genericDao.find(like
(employee));
See that the above uses an Employee that has a Department. Both the
Employee data and the Department data will be used in the geneated
query.
Using DAO methods to Named Queries mapping
In addition to using the API provided you can extend the API with
your own custom Named Queries.
To this you need to:
Define an interface with finder methods that start with "find"
Define named queries that match the name of your finder methods
Use the DaoFactory to configure a Generic DAO
Use the new finder methods
Define an interface with finder methods that start with "find"
package org.crank.crud.test.dao; import java.util.List; import
org.crank.crud.GenericDao; import
org.crank.crud.test.model.Employee; public interface EmployeeDAO
extends GenericDaoLong>{ List findEmployeesByDepartment(String
deptName); }
Notice that this interface extends GenericDao.
Define named queries that match the name of your finder methods
package org.crank.crud.test.model; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import
javax.persistence.GenerationType; import javax.persistence.Id;
import javax.persistence.ManyToOne; import
javax.persistence.NamedQueries; import
javax.persistence.NamedQuery; @Entity @NamedQueries( { @NamedQuery
(name="Employee.findEmployeesByDepartment", query="from Employee
employee where employee.department.name=?") }) public class
Employee { @Id @GeneratedValue( strategy = GenerationType.AUTO )
private Long id; ...
Notice the name of the named query is findEmployeesByDepartment and
this matches the name in the EmployeeDAO interface.
Use the DaoFactory to configure a Generic DAO
"daoFactory" class="org.crank.crud.GenericDaoFactory"
abstract="true"> "transactionInterceptor"> "entityManagerFactory"
ref="entityManagerFactory" /> "genericDao" parent="daoFactory">
"interface"> org.crank.crud.test.dao.EmployeeDAO "bo" >
org.crank.crud.test.model.Employee "transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionIntercep
tor"> "0" ref="transactionManager" /> "1">
"org.springframework.transaction.annotation.AnnotationTransactionAttri
buteSource">
Notice that the daoFactory only has to be defined once per project
while the genericDao is defined per DAO object (per entity)
(perhaps a better name for this example would be employeeDao
instead of genericDao).
Use the new finder methods
EmployeeDAO employeeDAO = (EmployeeDAO) this.genericDao; List
employees = employeeDAO.findEmployeesByDepartment("Engineering");
The first one may be somewhat difficult to setup, but your next
finder method is a mere matter of adding it to the DAO interface
and then creating the named query.
see http://code.google.com/p/krank/ for more details.
--Rick Hightower
Email: rhightower AT arc DASH mind DOT com
Run more. Lift more. Play more. Play hard. Procrastinate less.
Don't waste time. Time is short. Be bold. Be nice.
"I'm personally looking forward to having my ideas used and
improved on by others." --Paul Penfield, Jr (Engineer, MIT)
Warner Onstine - Programmer/Author
New book on Tapestry 4!
Tapestry 101 available at http://sourcebeat.com/books/tapestrylive.html
[EMAIL PROTECTED]
http://warneronstine.com/blog
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]