Как объединить два несвязанных объекта с помощью 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();

Это должно работать для вашего случая.


Как я объяснил в в этой статье, у вас есть два варианта:

  1. поскольку 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();
    
  2. до 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 имеет реализована такая функция

С Hibernate docs:

предложение 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

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

Но если вы объединяете эти таблицы только для некоторых случайных целей, вы можете использовать критерии и вручную загружать данные из каждой таблицы и складывать их вместе. (и да, вы можете иметь данные этих таблиц отдельно, если для адреса и фотографии есть два отдельных класса и таблицы)


то, что вы ищете

  1. бумага HQL
  2. присоединиться к полям, которые вы не смоделировали как отношения
  3. Левое Соединение

(в то время, когда вопрос был впервые задан, и этот ответ был дан) Hibernate поддерживает тета-соединение, которое позволяет вам делать 1 & 2. Однако для стиля Theta join доступно только внутреннее соединение.

лично я бы рекомендовал вам моделировать правильное отношения, поэтому вам просто нужен 1 & 3, который хорошо поддерживается в HQL.

(другой ответ фактически предоставил обновление новой функции Hibernate, которая предоставляет такую функцию, на которую вы можете просто ссылаться)