|
Listing 5. Generic DAO implemented as a service
@Stateless
@Local(CrudService.class)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public class CrudServiceBean implements CrudService {
@PersistenceContext
EntityManager em;
public <T> T create(T t) {
this.em.persist(t);
this.em.flush();
this.em.refresh(t);
return t;
}
@SuppressWarnings("unchecked")
public <T> T find(Class<T> type,Object id) {
return (T) this.em.find(type, id);
}
public void delete(Object t) {
Object ref = this.em.getReference(t.getClass(), t);
this.em.remove(ref);
}
public <T> T update(T t) {
return (T)this.em.merge(t);
}
public List findWithNamedQuery(String namedQueryName){
return this.em.createNamedQuery(namedQueryName).getResultList();
}
public List findWithNamedQuery(String namedQueryName, Map<String,Object> parameters){
return findWithNamedQuery(namedQueryName, parameters, 0);
}
public List findWithNamedQuery(String queryName, int resultLimit) {
return this.em.createNamedQuery(queryName).
setMaxResults(resultLimit).
getResultList();
}
public List findByNativeQuery(String sql, Class type) {
return this.em.createNativeQuery(sql, type).getResultList();
}
public List findWithNamedQuery(String namedQueryName, Map<String,Object> parameters,int resultLimit){
Set<Entry<String, Object>> rawParameters = parameters.entrySet();
Query query = this.em.createNamedQuery(namedQueryName);
if(resultLimit > 0)
query.setMaxResults(resultLimit);
for (Entry<String, Object> entry : rawParameters) {
query.setParameter(entry.getKey(), entry.getValue());
}
return query.getResultList();
}
}
More challenging are the query methods. You can't know the number of query parameters and their names when you develop the DAO service, so you must provide them in a generic way. Listing 6 shows the creation of query parameters in a fluent way with the Builder pattern.
Listing 6. The builder for query parameters
public class QueryParameter {
private Map<String,Object> parameters = null;
private QueryParameter(String name,Object value){
this.parameters = new HashMap<String,Object>();
this.parameters.put(name, value);
}
public static QueryParameter with(String name,Object value){
return new QueryParameter(name, value);
}
public QueryParameter and(String name,Object value){
this.parameters.put(name, value);
return this;
}
public Map<String,Object> parameters(){
return this.parameters;
}
}
The most suitable data structure for the transportation of query parameters is a java.util.Map, but it's rather inconvenient to create. The simple QueryParameter builder makes the construction of the query parameters more convenient and fluent. Listing 7 shows the use of the QueryParameter builder to construct the parameters.
Listing 7. The fluent way to construct a query parameter
import static ...dataservice.QueryParameter.*;
public List<Order> findOrdersForCustomer(int customerId){
return this.crudService.findWithNamedQuery(Order.findByCustomerId,
with("customerId", customerId).
parameters());
The static with() method creates a new QueryParameter instance. It enables a static import and makes the qualification with the QueryParameter superfluous. The and() method just puts the parameters into the internal Map and returns the QueryParameter again, which makes the construction fluent. Finally, the method parameters return only the internal Map, which can be directly passed to the CrudService. |
|