I have an abstract DAO class which uses parameterized types E
(Entity) and K
(Primary Key). In every entity I have a @NamedQuery
. I want to dynamically invoke this named query without knowing its exact name and parameter name.
As an example, imagine the following entity City
@Entity(name="CITY")
@NamedQuery(
name="findCityByname",
query="FROM CITY c WHERE name = :CityName"
)
public class City {
// ...
}
and this CityDao
public class CityDao extends AbstractDao<City, Long> {
public CityDao() {
super(City.class);
}
}
How should I implement the findByName()
method in AbstractDao
so that I don't need to know the exact name and parameter name?
public abstract class AbstractDao<E, K> implements Dao<E, K> {
@PersistenceContext
protected EntityManager entityManager;
protected Class<E> entityClass;
protected AbstractDao(Class<E> entityClass) {
this.entityClass = entityClass;
}
@Override
public E findByName(String name) {
try {
return (E) entityManager
.createNamedQuery("findCityByName")
.setParameter("CityName", name)
.getSingleResult();
} catch(Exception e) {
return null;
}
}
// ...
}
A named query is a predefined query that you create and associate with a container-managed entity (see "Using Annotations"). At deployment time, OC4J stores named queries on the EntityManager . At run time, you can use the EntityManager to acquire, configure, and execute a named query.
The EntityManager interface provides the createNativeQuery method for it. It returns an implementation of the Query interface, which is the same that you get when you call the createQuery method to create a JPQL query.
Query, written in Java Persistence Query Language (JPQL) syntax. NativeQuery, written in plain SQL syntax. Criteria API Query, constructed programmatically via different methods.
The naming convention for named queries is usually <Entity Name>.findBy<PropertyAndAnotherProperty>
, "City.findByName" in your example, so I would try to change the named queries to follow this pattern. The parameter to this query should then also have the same name, or you could use positional parameters. Your find method would then turn into
@Override
public E findByName(String name) {
E entity = null;
try {
return (E)entityManager.createNamedQuery(myClass.getSimpleName() + ".findByName")
.setParameter("name", name)
.getSingleResult();
} catch (Exception ex) {
return null;
}
}
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