Как объединить два несвязанных объекта с помощью JPA и Hibernate
У меня есть две таблицы - одна с адресом и еще с фотографиями. Единственное общее поле между ними является PersonID. Они были сопоставлены с двумя классами POJO адрес и фото. Я смог получить подробную информацию в этих таблицах, создав критерии и добавив ограничения на поля . Как мы должны написать соединение на двух таблицах. Можно ли получить результат в виде двух объектов-адреса и фотографии.
Я хочу сделать левое соединение, чтобы я мог получить записи людей и без фотографий. Я читал, что это возможно только с помощью hql, но можно ли это сделать с помощью критериев?
6 ответов
вы можете легко написать запрос HQL, который вернет результат в виде двух объектов с помощью тета-соединения (как отметил Адриан). Вот пример:
String queryText = "select address, photo from Address address, Photo photo where address.personID=photo.personId";
List<Object[]> rows = session.createQuery(queryText).list();
for (Object[] row: rows) {
System.out.println(" ------- ");
System.out.println("Address object: " + row[0]);
System.out.println("Photo object: " + row[1]);
}
Как вы можете видеть, запрос возвращает список массивов Object [], который представляет каждую извлеченную строку. Первый элемент этого массива будет содержать один obejct, а второй - другой.
EDIT:
в случае левого соединения, я думаю, вам нужно использовать собственный SQL-запрос (не HQL-запрос). Вот как вы можете это сделать это:
String queryText = "select address.*, photo.* from ADDRESS address
left join PHOTO photo on (address.person_id=photo.person_id)";
List<Object[]> rows = sess.createSQLQuery(queryText)
.addEntity("address", Address.class)
.addEntity("photo", Photo.class)
.list();
Это должно работать для вашего случая.
Как я объяснил в в этой статье, у вас есть два варианта:
-
поскольку Hibernate 5.1, вы можете использовать ad-hoc присоединяется для несвязанных лиц.
Tuple postViewCount = entityManager.createQuery( "select p as post, count(pv) as page_views " + "from Post p " + "left join PageView pv on p.slug = pv.slug " + "where p.title = :title " + "group by p", Tuple.class) .setParameter("title", "High-Performance Java Persistence") .getSingleResult();
-
до Hibernate 5.1 вы могли использовать только соединения в тета-стиле. Однако соединение в тета-стиле эквивалентно equijoin, поэтому вы можете эмулировать только внутренние соединения, а не внешние соединения.
List<Tuple> postViewCount = entityManager.createQuery( "select p as post, count(pv) as page_views " + "from Post p, PageView pv " + "where p.title = :title and " + " ( p.slug = pv.slug ) " + "group by p", Tuple.class) .setParameter("title", "Presentations") .getResultList();
для более подробной информации, проверить в этой статье.
наконец-то после 12 лет команда Hibernate имеет реализована такая функция
предложение FROM также может содержать явные соединения отношений с помощью ключевого слова join. Эти соединения могут быть внутренними или левыми внешними соединениями стиля.
List<Person> persons = entityManager.createQuery(
"select distinct pr " +
"from Person pr " +
"join pr.phones ph " +
"where ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.MOBILE )
.getResultList();
List<Person> persons = entityManager.createQuery(
"select distinct pr " +
"from Person pr " +
"left join pr.phones ph " +
"where ph is null " +
" or ph.type = :phoneType", Person.class )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.getResultList();
или вы можете использовать WITH
и ON
ключевые слова. Замечание о тех
важным отличием является то, что в сгенерированном SQL условия В С/О п. в рамках пункта в созданном SQL, в отличие от других запросов в этом разделе, где Условия HQL/JPQL становятся частью предложения WHERE в сгенерированном язык SQL.
пример
List<Object[]> personsAndPhones = session.createQuery(
"select pr.name, ph.number " +
"from Person pr " +
"left join pr.phones ph with ph.type = :phoneType " )
.setParameter( "phoneType", PhoneType.LAND_LINE )
.list();
в настоящее время я хочу попробовать новую функцию.
объединение двух несвязанных объектов возможно в Hibernate 5.1.
например :
select objA from ObjectA objA
JOIN ObjectB objB on objB.variable = objA.variable
where objA.id = 1
лучше всего иметь класс, содержащий те классы, к которым вы хотите присоединиться, чтобы иметь их все вместе.
Но если вы объединяете эти таблицы только для некоторых случайных целей, вы можете использовать критерии и вручную загружать данные из каждой таблицы и складывать их вместе. (и да, вы можете иметь данные этих таблиц отдельно, если для адреса и фотографии есть два отдельных класса и таблицы)
то, что вы ищете
- бумага HQL
- присоединиться к полям, которые вы не смоделировали как отношения
- Левое Соединение
(в то время, когда вопрос был впервые задан, и этот ответ был дан) Hibernate поддерживает тета-соединение, которое позволяет вам делать 1 & 2. Однако для стиля Theta join доступно только внутреннее соединение.
лично я бы рекомендовал вам моделировать правильное отношения, поэтому вам просто нужен 1 & 3, который хорошо поддерживается в HQL.
(другой ответ фактически предоставил обновление новой функции Hibernate, которая предоставляет такую функцию, на которую вы можете просто ссылаться)