Создание критерия гибернации, который может фильтровать по ссылочной сущности

#java #hibernate #persistence #criteria

#java #гибернация #постоянство #критерии

Вопрос:

У меня есть объект (PersonQuestionsEntity), который имеет PersonEntity и QuestionEntity в качестве первичного ключа. Я использую составной ключ, чтобы отразить эту взаимосвязь.

Теперь я хочу создать объект Criteria, который может выполнять следующее: Находить все объекты PersonQuestion для заданного QuestionID и возраста человека.

Вот моя попытка создать критерий для этого:

     Session session = getHibernateTemplate().getSessionFactory().openSession();
    Criteria criteria = session.createCriteria(PersonQuestionsEntity.class);
    criteria.add(Restrictions.eq("question.questionId", "87"));
    criteria = criteria.createCriteria("person");
    criteria.add(Restrictions.eq("age", 23));
    criteria.setMaxResults(100);
    List l = criteria.list();
  

Проблема в том, что я получаю эту ошибку:

 Caused by: java.sql.SQLException: ORA-00904: "PERSONENTI1_"."AGE": invalid identifier
  

В сгенерированном SQL кажется, что на person указано PERSONENTI4, а не PERSONENTI1. Если я скопирую SQL и запущу его с PERSONENTIT4 вместо PERSONENTI4, это сработает (вроде как — похоже, что выполняется какое-то декартово объединение).

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

PersonQuestionsEntity

 @Entity
@IdClass(com.anonymous.model.PersonQuestionsKey.class)
@Table(name = "PERSON_QUESTIONS")
public class PersonQuestionsEntity implements Serializable
{
    private static final long serialVersionUID = -8254277382097937813L;

    @Id
    @ManyToOne
    @JoinColumn(name = "USER_NAME", nullable = false)
    private PersonEntity person;

    @Id
    @ManyToOne
    @JoinColumn(name = "QUESTION_ID", nullable = false)
    private QuestionEntity question;

    @Column(name = "THEIR_ANSWER")
    private int theirAnswer;
}
  

PersonEntity

 @Entity
@Table(name = "PERSON")

public class PersonEntity implements Serializable
{
    private static final long serialVersionUID = -1699435979266209440L;

    @Id
    @Column(name = "USER_NAME", length = 20, nullable = false)
    private String userName;

    @Column(name = "USER_NAME_REAL", length = 20, nullable = false)
    private String userNameReal;

    @Column(name = "AGE", nullable = false)
    private int age;
}
  

PersonQuestionsKey

    @Embeddable
    public class PersonQuestionsKey implements Serializable
    {
        private static final long serialVersionUID = -264160855961369405L;

        @Id
        @ManyToOne
        @JoinColumn(name = "USER_NAME", nullable = false)
        private PersonEntity person;

        @Id
        @ManyToOne
        @JoinColumn(name = "QUESTION_ID", nullable = false)
        private QuestionEntity question;

}
  

Комментарии:

1. Как вы решили проблему?

2. @MikhailBatcer Я, честно говоря, не помню. Я проверю код сегодня вечером или завтра и посмотрю, смогу ли я понять, что я сделал — прошло довольно много времени, и это был просто хобби-проект.

Ответ №1:

Прежде всего, вам действительно не нужны внутренние критерии, просто используйте:

 Критерии criteria = session.createCriteria(PersonQuestionsEntity.class );
 criterions.add(Ограничения.eq("вопрос.QuestionID", "87"));
 criterions.add(Restrictions.eq("person.age", 23));
 criterions.setMaxResults(100);
 Список l = criterions.list();

Во-вторых (что касается типа соединения), в таких случаях я обычно использую HQL, который создает внутренние соединения. HQL может выглядеть следующим образом:

от PersonQeustionEntity, где вопрос.QuestionID = :QuestionID 
 и person.age = :возраст

в результирующем Query объекте вы можете задать параметры questionId и age желаемые входные данные.

Комментарии:

1. Я хотел использовать критерии, потому что я хотел бы предоставить множество различных вариантов для фильтрации результатов (реальный PersonEntity имеет намного больше полей, чем этот сокращенный). Кроме того, я попробовал код, который вы показали при первом запуске, но он не сработал. Я получаю эту ошибку: org.hibernate. Исключение QueryException: не удалось разрешить свойство: person.age of: com.anonymous.model. PersonQuestionsEntity. Мне интересно, не портит ли что-нибудь мое использование составного ключа?

2. если вы выполняете только критерии QuestionID, работает ли это правильно? Ошибка, которую вы написали, выглядит так, как будто у вас проблема с отображением объектов, но я не могу быть уверен, что это из-за используемого вами составного ключа.

3. Это работает должным образом, если я использую только критерии QuestionID. Мне придется перепроверить, когда я вернусь домой, но я думаю, что критерии имени пользователя пользователя также работают.

4. createCriteria устарел с версии 5.2. Есть ли какая-либо альтернатива, которая была бы почти такой же чистой, как отображаемая здесь? Метод, показанный в руководствах, довольно уродлив…