So, After a 10+ year break I'm coming back to Java and trying out stuff with JPA and Java generics. I've created a generics based findAll(other)
JPA query that basically does
SELECT * FROM source WHERE other_id = other.id;
This is where I'm up to. It works, but I'm wondering if there's a better, cleaner way to do it. Using ManagedType
was hard, and there's not much complete documentation or simple examples around.
I've decided to keep my code as generic as possible (no pun intended) so I use JPA2.
This is the root of all Entity Classes. I probably don't need it, but it stops me from having basic mistakes.
import java.io.Serializable;
public abstract class DomainObject implements Serializable {
private static final long serialVersionUID = 1L;
public abstract void setId(Long id);
public abstract Long getId();
}
This is the abstract DAO class. I extend this for the implementation classes as I need to be more specific doing other activities - mostly making sure lazy sets are loaded.
public abstract class GenericDAOImpl<T extends DomainObject, T2 extends DomainObject> implements GenericDAO<T, T2> {
private Class<T> type;
@PersistenceContext
protected EntityManager entityManager;
public GenericDAOImpl(Class<T> type) {
super();
this.type = type;
}
... save and delete classes go here
@Override
public List<T> findAll(T2 where) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(type);
Root<T> rootQuery = criteriaQuery.from(type);
if (where != null) {
EntityType<T> entity = entityManager.getMetamodel().entity(type);
SingularAttribute<? super T, ?> attribute = null;
for (SingularAttribute<? super T, ?> singleAttribute: entity.getSingularAttributes()) {
// loop through all attributes that match this class
if (singleAttribute.getJavaType().equals(where.getClass())) {
// winner!
attribute = singleAttribute;
break;
}
}
// where t.object = object.getID()
criteriaQuery.where(criteriaBuilder.equal(rootQuery.get(attribute), where));
}
criteriaQuery.select(rootQuery);
TypedQuery<T> query = entityManager.createQuery(criteriaQuery);
// need this to make sure we have a clean list?
// entityManager.clear();
return query.getResultList();
}
Any suggestions? If anything, I want this out there so other people can make use of it.
Hat tip to Adam Bien if you don't want to use createQuery
with a String
and want type safety:
@PersistenceContext EntityManager em; public List<ConfigurationEntry> allEntries() { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<ConfigurationEntry> cq = cb.createQuery(ConfigurationEntry.class); Root<ConfigurationEntry> rootEntry = cq.from(ConfigurationEntry.class); CriteriaQuery<ConfigurationEntry> all = cq.select(rootEntry); TypedQuery<ConfigurationEntry> allQuery = em.createQuery(all); return allQuery.getResultList(); }
http://www.adam-bien.com/roller/abien/entry/selecting_all_jpa_entities_as
I found this page very useful
https://code.google.com/p/spring-finance-manager/source/browse/trunk/src/main/java/net/stsmedia/financemanager/dao/GenericDAOWithJPA.java?r=2
public abstract class GenericDAOWithJPA<T, ID extends Serializable> {
private Class<T> persistentClass;
//This you might want to get injected by the container
protected EntityManager entityManager;
@SuppressWarnings("unchecked")
public GenericDAOWithJPA() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
@SuppressWarnings("unchecked")
public List<T> findAll() {
return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").getResultList();
}
}
you can also use a namedQuery named findAll for all your entities and call it in your generic FindAll with
entityManager.createNamedQuery(persistentClass.getSimpleName()+"findAll").getResultList();
This will work, and if you need where statement you can add it as parameter.
class GenericDAOWithJPA<T, ID extends Serializable> {
.......
public List<T> findAll() {
return entityManager.createQuery("Select t from " + persistentClass.getSimpleName() + " t").getResultList();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With