запрос с критериями для связанных объектов - PullRequest
0 голосов
/ 11 мая 2011

Я боролся с этой проблемой запросов Hibernate, и я надеюсь, что я могу получить толчок в правильном направлении.

У меня есть объект с именем FlashCard, с которым связаны объекты, называемые тегами.FlashCard может иметь один или несколько тегов (например, как вопрос StackOverflow может быть назначен нескольким тегам).

Я пытаюсь использовать Hibernate для возврата всех карт Flash, которым назначены определенные теги.Например, я хотел бы запросить все FlashCards, имеющие ОБА «tag2» и «tag4».

Я пытался подойти к этому вопросу с помощью критериальных запросов, примеров запросов и HQL, но пока безуспешно.

Вот как выглядит база данных: mysql> select * from flashcard;

+--------------+------------+----------+
| FLASHCARD_ID | QUESTION   | ANSWER   |
+--------------+------------+----------+
|            1 | Question 1 | Answer 1 |
|            2 | Question 2 | Answer 2 |
|            3 | Question 3 | Answer 3 |
|            4 | Question 4 | Answer 4 |
+--------------+------------+----------+
4 rows in set (0.00 sec)

mysql> select * from tag;
+--------+------+
| TAG_ID | NAME |
+--------+------+
|      1 | tag1 |
|      3 | tag2 |
|      2 | tag3 |
|      4 | tag4 |
|      5 | tag5 |
+--------+------+
5 rows in set (0.00 sec)

mysql> select * from flashcard_tags;
+--------+--------------+
| TAG_ID | FLASHCARD_ID |
+--------+--------------+
|      2 |            1 |
|      3 |            1 |
|      4 |            1 |
|      3 |            2 |
|      4 |            2 |
|      5 |            2 |
|      3 |            3 |
+--------+--------------+
7 rows in set (0.00 sec)

Используя приведенные выше данные, вы можете видеть, что только FlashCard 1 и 2 имеют ОБА "tag2" и "tag4».

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

Пример 1 рабочего запроса SQL:

SELECT  f.*
FROM    (
        SELECT  flashcard_id
        FROM    tags t
        JOIN    flashcard_tags ft
        ON      ft.tag_id = t.tag_id
        WHERE   t.name IN ('tag2', 'tag4')
        GROUP BY
                flashcard_id
        HAVING  COUNT(*) = 2
        ) ft
JOIN    flashcard f
ON      f.flashcard_id = ft.flashcard_id

Пример 2 рабочего SQL-запроса:

SELECT f.*
FROM flashcard f
  INNER JOIN flashcard_tags ft1 ON f.FLASHCARD_ID = ft1.FLASHCARD_ID
  INNER JOIN tag t1 ON ft1.TAG_ID = t1.TAG_ID AND t1.NAME = 'tag2'
  INNER JOIN flashcard_tags ft2 ON f.FLASHCARD_ID = ft2.FLASHCARD_ID
  INNER JOIN tag t2 ON ft2.TAG_ID = t2.TAG_ID AND t2.NAME = 'tag4'

Вот как выглядят отображения Hibernate:

<hibernate-mapping>
   <class name="org.robbins.flashcards.model.FlashCard" table="FLASHCARD">
      <id name="flashCardId" type="int" column="FLASHCARD_ID">
         <meta attribute="scope-set">public</meta>
         <generator class="native" />
      </id>
      <property name="question" type="string">
         <meta attribute="use-in-tostring">true</meta>
         <column name="QUESTION" not-null="true" unique="true" />
      </property>
      <property name="answer" type="text">
         <meta attribute="use-in-tostring">true</meta>
         <column name="ANSWER" not-null="true" />
      </property>
      <set name="tags" table="FLASHCARD_TAGS">
         <meta attribute="field-description">Tags for this FlashCard</meta>
         <key column="FLASHCARD_ID" />
         <many-to-many class="org.robbins.flashcards.model.Tag"
            column="TAG_ID" />
      </set>
   </class>
</hibernate-mapping>

<hibernate-mapping>
   <class name="org.robbins.flashcards.model.Tag" table="TAG">
      <id name="tagId" type="int" column="TAG_ID">
         <meta attribute="scope-set">public</meta>
         <generator class="native" />
      </id>
      <property name="name" type="string">
         <meta attribute="use-in-tostring">true</meta>
         <column name="NAME" not-null="true" unique="true" />
      </property>
      <set name="flashcards" table="FLASHCARD_TAGS" inverse="true">
         <meta attribute="field-description">FlashCards for this Tag</meta>
         <key column="TAG_ID" />
         <many-to-many class="org.robbins.flashcards.model.FlashCard"
            column="FLASHCARD_ID" />
      </set>
   </class>
</hibernate-mapping>

Наконец, вот выдержка из сгенерированногоКласс FlashCard, где вы можете видеть связанные теги:

public class FlashCard  implements java.io.Serializable {
     private int flashCardId;
     private String question;
     private String answer;
     private Set<Tag> tags = new HashSet<Tag>(0);
}

Я столкнулся с проблемами при создании кода Hibernate, который будет получать тот же результат.Я попытался выполнить запрос Criteria, но узнал, что он не поддерживает предложение SQL «Имея» или не использует «подзапрос» в предложении From, как в примере SQL № 1.

Я попытался выполнить запрос по Примеру (передача в FlashCardПример, к которому были прикреплены два объекта Tag) и вообще не дал результатов.

Я также пытался заглянуть в HQL, но прочитал, что «подзапросы HQL могут встречаться только в предложениях select или where».

Вместо того, чтобы делать этот пост больше, я пока воздержусь от публикации примеров моего неудачного кода Hibernate.Я с удовольствием опубликую их, если это будет полезно.

Любая помощь очень ценится.Спасибо!

1 Ответ

1 голос
/ 11 мая 2011

Посмотрите на эту статью, в ней объясняется, как использовать HQL со многими отношениями.

http://www.sergiy.ca/how-to-write-many-to-many-search-queries-in-mysql-and-hibernate/

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