Easier JPA with Spring Data JPA
Database access in Java went through some steps:
Some would (and do) object that in such a use-case, there's no need for a DAO: the EntityManager just needs to be injected in the service class and used directly. This may be a relevant point-of-view, but only when there's no query for as soon as you go beyond that, you need to separate between data access and business logic.
In the second, you have to implement your own query with the CriteriaBuilder:
IMHO, these lines of code bring nothing to the table and just clutter our own code. By chance, some time ago, I found project
Hades, a product which was based on this conclusion and wrote simple code for you.Yes, SDJ provides you with a generic DAO, like so many frameworks around but here, wiring into the underlying implementation is handled by the framework, free of charge. For those that don't need them all and prefer the strict minimum, you can also use the following strategy, where you have to choose the methods from the list above (and use the annotation):
It sure is nice, but the best is yet to come. Remember the two above use-cases we had to write on our own? The first is simply handled by adding the unqualified query name to the interface like so:
The second use-case, finding all employees, is provided in the JPA repository. But let's pretend for a second we have a WHERE clause, for example on the first name. SDJ is capable of handling simple queries based on the method name:
We had to code only an interface and its methods: no implementation code nor metamodel generation was involved! Don't worry, if you need to implement some complex queries, SDJ let you wire your own implementation.
- at first, pure JDBC
- proprietary frameworks
- standards such as EJB Entities and JDO
- OpenSource frameworks such as Hibernate and EclipseLink (known as TopLink at the time)
JPA2 to the rescue
At last, JPA2 supplies something usable in a real-world application. And yet, I feel there's still so much boilerplate code to write a simple CRUD DAO:01.
public
class
JpaDao {
02.
03.
@PersistenceContext
04.
private
EntityManager em;
05.
06.
private
Class managedClass;
07.
08.
private
JpaDao(Class managedClass) {
09.
10.
this
.managedClass = managedClass;
11.
}
12.
13.
public
void
persist(E entity) {
14.
15.
em.persist(entity);
16.
}
17.
18.
public
void
remove(E entity) {
19.
20.
em.remove(entity);
21.
}
22.
23.
public
E findById(PK id) {
24.
25.
return
em.find(managedClass, id);
26.
}
27.
}
Boilerplate code in JPA2
Two simple use-cases highlight the useless boilerplate code in JPA 2: @NamedQuery and simple criteria queries. In the first case, you have to get the handle on the named query through the entity manager, then set potential parameters like so:1.
Query query = em.createNamedQuery(
"Employee.findHighestPaidEmployee"
);
1.
CriteriaBuilder builder = em.getCriteriaBuilder();
2.
3.
CriteriaQuery query = builder.createQuery(Person.
class
);
4.
5.
Root fromPerson = query.from(Person.
class
);
6.
7.
return
em.createQuery(query.select(fromPerson)).getResultList();
Spring Data JPA
Given the fate of some excellent OpenSource projects, Hades fared much better since it has been brought into the Spring ecosystem under the name Spring Data JPA. Out of the box, SDJ provides DAOs that have advanced CRUD features. For example, the following interface can be used as-is: [java]public interface EmployeeRepository extends JPARepository[/java] Given some Spring magic, an implementation will be provided at runtime with the following methods:- void deleteAllInBatch()
- void deleteInBatch(Iterable
entities) - List
findAll() - List
findAll(Sort sort) - void flush()
Listsave(Iterableentities)Employee saveAndFlush(Employee entity)PagefindAll(Pageable pageable) IterablefindAll(Sort sort) long count()void delete(ID id)void delete(Iterable entities)void delete(Employee entity)void deleteAll()boolean exists(Long id)IterablefindAll() IterablefindAll(Iterable ids) Employee findOne(Long id)Iterablesave(Iterableentities)S save(S entity)
1.
]
@RepositoryDefinition
(domainClass = Employee.
class
, idClass = Long.
class
)
2.
public
interface
EmployeeRepository {
3.
4.
long
count();
5.
6.
Employee save(Employee employee);
7.
}
1.
@RepositoryDefinition
(domainClass = Employee.
class
, idClass = Long.
class
)
2.
public
interface
EmployeeRepository {
3.
4.
...
5.
6.
Employee findHighestPaidEmployee();
7.
}
1.
@RepositoryDefinition
(domainClass = Employee.
class
, idClass = Long.
class
)
2.
public
interface
EmployeeRepository {
3.
4.
...
5.
6.
List findByLastname(String firstName);
7.
}
Conclusion
If you're already a Spring user, Spring Data JPA is really (really!) a must. If you're not, you're welcome to test it to see its added value by yourself. IMHO, SDJ is one of the reason JavaEE has not killed Spring yet: it bridged the injection part, but the boilerplate code is still around every corner. This article is not a how-to but a teaser to let you into SDJ. You can find the sources for this article here, in Maven/Eclipse format. To go further:- Spring Data JPA documentation
- Spring Data JPA Javadocs
No comments:
Post a Comment