2013-11-19 3 views
0

Я новичок в JPQL и имею некоторые проблемы с тем, что, по моему мнению, может быть довольно простым запросом. Пожалуйста, объясните, возможно ли следующее.JPQL выбрать из нескольких таблиц

У меня есть два несвязанные столы: «клиенты» и «купцы». Они оба содержат поле под названием «имя пользователя». Есть ли запрос, который вернет мне запись «имя пользователя», которая появляется в любой таблице, и которая соответствует введенному мной значению?

Query query = entityManager.createQuery("select c from Customers c where c.username = :username");     
query.setParameter("username", username_); 

Нечто подобное, но для обеих столов.

+0

Возможный дубликат http://stackoverflow.com/questions/10758169/joining-two-unrelated-tables-in-hibernate – Jayasagar

ответ

0

Похоже, вы хотите, чтобы данное имя пользователя соответствовало Customer или Merchant. Поскольку две таблицы не связаны друг с другом, чтобы сделать это с помощью одного запроса, я считаю, что вам нужно будет сформировать cartesian product (соедините каждую строку из одной таблицы с каждой строкой в ​​другой). Как вы можете себе представить, это может быть очень неэффективно. Вы лучше делать два простых запросов:

try { 
    Customer c = em.createQuery("SELECT c FROM Customer c WHERE c.username = :username", Customer.class) 
       .setParameter("username", username) 
       .getSingleResult(); 

    // ... do something with the customer ... 
} catch (NoResultException e) { 
    // user wasn't found in the customer table, try merchant: 
    try { 
    Merchant m = em.createQuery("SELECT m FROM Merchant m WHERE m.username = :username", Merchant.class) 
        .setParameter("username", username) 
        .getSingleResult(); 

    // ... do something with the merchant ... 
    } catch (NoResultException e) { 
    // user wasn't found in either table 
    } 
} 

Примечание: Я предполагаю, что username является уникальным в пределах Customer и Merchant.

Обратите внимание, что этот подход выполнит только второй запрос, если мы не найдем пользователя с первым. Если вам не нужно возвращать объект (т. Е. Просто нужно проверить, существует ли он), вы можете упростить это с помощью двух запросов count. Count-запросы всегда возвращают результат, поэтому вам не нужно будет ловить NoResultException s

+0

Я просто хочу добавить, что если бы это был я, работа в такой ситуации повысила бы красный флаг, который, возможно, я должен пересмотреть дизайн. Например, почему «Клиент» и «Торговец» не распространяют общий класс «Пользователь»? Если они это сделали, вы можете просто запросить «Пользователь». – DannyMo

+0

Спасибо за ответ. У меня действительно есть очень похожее решение, я просто задавался вопросом, был ли более сжатый способ сделать это в JPQL. Что касается расширения общего класса, я смущен относительно того, как это уменьшит количество требуемого кода JPQL. Вы говорите, что я могу сопоставить все пользовательские таблицы с классом 'User', а затем запустить что-то вроде:' select u от пользователя, где u.username =: username'? – Caiman

+0

@Caiman Да, принимая пользователей 'Customer' и' Merchant' _are_, вы можете перенести обычные вещи, такие как имя пользователя, в суперкласс User. У вас все еще есть «Клиент» и «Торговец», которые содержат какие-либо их специфические атрибуты. У меня нет всей картины, так что может получиться, что это не очень хорошее изменение ... это была просто мысль. Ознакомьтесь с [учебником] (http://docs.oracle.com/javaee/7/tutorial/doc/persistence-intro002.htm#BNBQN) для получения дополнительной информации. – DannyMo

0

Если это действительно не работает: (Я думаю, что это так, по крайней мере, с CriteriaQuery, я уверен, что это так) Запрос запроса = entityManager.createQuery ("select c from Customers c, Merchants m where c.username =: имя пользователя и m.username = c.username ");
query.setParameter ("username", username_);

Вы всегда можете это сделать: запрос Query = entityManager.createQuery ("выберите C от клиентов с, где c.username =: имя пользователя и c.username в (выберите m.username от Купеческого м)");
query.setParameter ("username", username_);

+0

Спасибо за ответ и извинения за мой отложенный ответ. Я могу сказать из вашего решения, что я не очень хорошо объяснил свой вопрос, так что я поеду еще раз. Я хочу проверить, совпадает ли мой вход с клиентом ** или ** с продавцом - если у вас есть запись в таблице клиентов с правильным именем пользователя, верните эту запись. Если нет, то проверьте таблицу торговцев, и если там нет совпадения, то ничего не возвращайте. Надеюсь, что это яснее. – Caiman

Смежные вопросы