2013-10-02 4 views
-1

почему этот запрос работает непосредственно на базе данных Postgres:почему это странное поведение OpenJpa?

select m from medicine_case m WHERE m.id IN (select m.id FROM medicine_case m LEFT OUTER JOIN patient ON m.patient=patient.id ORDER BY patient.surname ASC) 

И в OpenJPA с точным соответствующим типизированного запроса:

String sql = " select m from medicine_case m WHERE m.id IN (select m.id FROM medicine_case m LEFT OUTER JOIN " 
       + "patient ON m.patient=patient.id ORDER BY patient.surname ASC)"; 
     TypedQuery<MedicineCase> query = persistenceClient.createQueryMC(sql); 
     setParameter(query); 
     query.setFirstResult(first); 
     query.setMaxResults(count); 

дает мне:

org.apache.openjpa.persistence.ArgumentException: Encountered "m . id IN (select m . id FROM medicine_case m LEFT OUTER JOIN patient ON" at character 37, but expected: ["(", ")", "*",.... etc etc 

почему ??? ?? это так странно и делает меня сумасшедшим!

код, который создает запрос от менеджера объекта:

return entityManager.createQuery(sql, MedicineCase.class); 

и код, который выполняет это:

return query.getResultList().iterator();

+0

Вы уверены, что SQL работает в Postgres? Есть ли столбец «m»? – Thilo

+0

Между строкой, в которой вы инициализируете 'String sql' и' TypedQuery query', вы должны проверить значение 'sql' через точки останова или вывести' sql'. – nhgrif

+0

да, это работает, я выполнил его в консоли postgres ... и там нет столбца с именем m, но этот синтаксис означает, что вы хотите в результате получить объект m, представляющий таблицу, а не только список столбцов – andPat

ответ

2

Вы путаете SQL (что ожидает PostgreSQL) и HQL (это то, что ожидает EntityManager.createQuery()).

Это два разных языка. SQL работает с таблицами и столбцами, тогда как JPQL работает с объектами JPA, полями/свойствами и ассоциациями и переводится вашей реализацией JPA в SQL.

Если вы хотите выполнить SQL, вы должны использовать EntityManager.createNativeQuery().

+0

Большое спасибо! Я новичок в jpa, и я не знаю этой разницы ... К сожалению, я не могу использовать createNativeQuery, потому что мне нужно получить сложный объект, а простой запрос недостаточно мощный, чтобы дать мне кометный объект MedicineCase (который содержит отношения с другими объектами), как я могу реализовать IN-clause в JPQL? Вы можете мне помочь? – andPat

+0

Если вы даже не знаете, что существует JPQL, сначала прочитайте учебник или книгу, затем попробуйте что-нибудь, прежде чем обращаться за помощью. Тем не менее, ваш запрос слишком сложный. Просто запуск внутреннего запроса приведет к такому же результату. –

+0

Большое спасибо, я попросил о помощи только для ограничения рабочего времени. Не могли бы вы предложить мне хороший учебник по Интернету? – andPat

0

в jpql становится немного иначе:

String sql = "select m from " + MedicineCase.class.getSimpleName() + " m WHERE m.id IN :mcList"; 
TypedQuery<MedicineCase> query = persistenceClient.createQueryMC(sql); 
     query.setParameter("mcList", persistenceClient.executeQueryMCId(persistenceClient.createQueryMCId(createSql() 
       + addOrders()))); 
     setParameter(query); 
     query.setFirstResult(first); 
     query.setMaxResults(count); 
     return persistenceClient.executeQueryMC(query); 

где createSql возвращает:

sql.append("select m.id ").append(" FROM ").append(MedicineCase.class.getSimpleName()).append(" m"); 

и addOrders:

" LEFT OUTER JOIN m.patient p ORDER BY p.surname ASC 
Смежные вопросы