Как присоединиться к двум несвязанным объектам, использующим JPA и Hibernate
У меня две таблицы: одна содержит адрес, а другая - фотографии. Единственным общим полем между ними является PersonID. Они были сопоставлены с двумя адресами POJO Classes и фотографией. Я смог получить данные в этих таблицах, создав критерии и добавив ограничения на поля. Как мы должны писать объединение в двух таблицах. Можно ли получить результат как два объекта -Address и Фото.
Я хочу сделать левое соединение, чтобы я мог записывать людей без фотографий. Я читал, что это возможно только с использованием hql, но возможно ли это, используя критерии?
Ответы
Ответ 1
Вы можете легко написать запрос HQL, который будет возвращать результат в виде двух объектов, использующих Theta Join (как заметил Адриан). Вот пример:
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, а второй - другой.
РЕДАКТИРОВАТЬ:
В случае левого соединения, я думаю, вам нужно использовать собственный 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();
Это должно работать для вашего дела.
Ответ 2
Как я объяснил в этой статье, у вас есть два варианта:
-
С 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, поэтому вы можете только эмулировать INNER JOINs, а не OUTER JOINs.
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();
Для получения дополнительной информации ознакомьтесь с этой статьей.
Ответ 3
Наконец, через 12 лет команда Hibernate реализовала такую функцию
Из документов 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 условия предложения WITH/ON являются частью предложения ON в сгенерированном SQL, в отличие от других запросов в этом разделе, где условия HQL/JPQL являются частью ГДЕ в сгенерированном 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();
В настоящее время я хочу попробовать новую функцию.
Ответ 4
Объединение двух несвязанных объектов возможно в Hibernate 5.1.
Например:
select objA from ObjectA objA
JOIN ObjectB objB on objB.variable = objA.variable
where objA.id = 1
Ответ 5
Что вы ищете
- HQL
- Присоединяйтесь к полям, которые вы не моделировали как отношения
- Left Join
(В то время, когда вопрос был задан первым, и этот ответ был дан) Hibernate поддерживает Theta Join, который позволяет вам делать 1 и 2. Однако для стиля тета-соединения доступно только внутреннее соединение.
Лично я бы рекомендовал вам моделировать правильные отношения, поэтому вам нужно всего лишь 1 и 3, которые хорошо поддерживаются в HQL.
(Еще один ответ на самом деле предоставил обновленную информацию о новой функции Hibernate, которая предоставляет такую функцию, о которой вы можете просто обратиться)
Ответ 6
Лучше всего иметь класс, содержащий те классы, к которым вы хотите присоединиться, чтобы объединить их все.
Но если вы присоединяетесь к этим таблицам только для некоторых случайных целей, вы можете использовать критерии и вручную загружать данные из каждой таблицы и складывать их вместе. (и да, вы можете иметь данные этих таблиц отдельно, если для адреса и фотографии есть два отдельных класса и таблицы)