Общая реализация для выполнения именованных запросов - PullRequest
0 голосов
/ 02 декабря 2018

Я пытаюсь реализовать универсальный класс (GenericDaoImpl<T,E>), который содержит метод, который выполняет NamedQueries (findByNamedQuery(..)).Этот метод запрашивает именованное имя запроса и массив объектов (параметры).Я должен повторить их и связать эти параметры с именованным запросом.

Я не могу изменить сигнатуру метода.

public abstract class GenericDaoImpl<T, E> implements GenericDao<T, E> {

    @PersistenceContext(unitName="MyUnit")
    protected EntityManager em;
    private Class<T> persistentClass;

    @SuppressWarnings("unchecked")
    public GenericDaoImpl() {
        this.persistentClass = getPersistentClass();
    }

    public void setPersistentClass(Class<T> persistentClass) {
        this.persistentClass = persistentClass;
    }

    public Class<T> getPersistentClass() {
        Class<?>[] typeArguments = TypeResolver.resolveRawArguments(GenericDao.class, getClass());
        this.persistentClass = (Class<T>) typeArguments[0];
        return persistentClass;
    }

    ....

    @Transactional
    public void save(T entity) {
        em.persist(entity);
    }

    @Transactional
    public void update(T entity) {
        em.merge(entity);
    }

    @Transactional
    public void delete(E id) {
        em.remove(em.find(persistentClass,id));
    }

    ...

    public List<T> findByNamedQuery(String queryName, Object... params) {
        Query q = this.em.createNamedQuery(queryName,persistentClass);
        for(int i =1;i<params.length-1;i++){
            q.setParameter(i, params[i]);
        }
        return (List<T>)q.getResultList();
    }

}

Теперь, учитывая этот именованный запрос:

@NamedQuery(name="Office.findByStreetAndCity",query="SELECT o from Office o JOIN o.address a WHERE a.street=:street AND a.city=:city"),

Давайте выполним метод:

String[] params= {"Mount Eden Road", "London"};
List<Office> offices= dao.findByNamedQuery("Office.findByStreetAndCity", params);

Но это не сработает:

java.lang.IllegalArgumentException: org.hibernate.QueryException: Не все именованные параметры были установлены: [город, улица] [ВЫБРАТЬ o из офиса o ПРИСОЕДИНИТЬСЯ o.адреса ГДЕ a.street =: street AND a.city =: city]

Я не очень знаком с JPA, но думаю, чтоэто не удается, потому что мы не можем установить параметры по индексу при использовании именованных параметров в определении NamedQuery.

1 Ответ

0 голосов
/ 02 декабря 2018

Ваше предположение верно, и вы смешиваете между ними.

Вы можете либо продолжить использовать setParameter("street", "Mount Eden Road") и изменить свою подпись на что-то вроде public List<T> findByNamedQuery(String queryName, Map<String, Object> params), либо переписать свой запрос, чтобы использовать позиционные параметры (начиная с 0):

SELECT o from Office o JOIN o.address a WHERE a.street=? AND a.city=?

for(int i = 0; i < params.length; i++){
    q.setParameter(i, params[i]);
}
...