2016-12-29 3 views
2

У меня есть две таблицы.Критерии JPA Присоединиться к таблице OneToMany, где предложение не работает

CREATE TABLE public.question 
(
    id  SERIAL PRIMARY KEY 
    , day  VARCHAR(2)  NOT NULL 
    , month VARCHAR(2)  NOT NULL 
    , year  VARCHAR(4)   NOT NULL 
); 

CREATE TABLE public.question_translation 
(
    id SERIAL PRIMARY KEY 
    , question_id INT REFERENCES public.question(id) NOT NULL 
    , question_text TEXT        NOT NULL 
    , language  VARCHAR(2)       NOT NULL 
); 

Теперь я хочу создать критерии для извлечения вопроса. SQL как это:

SELECT * FROM question q LEFT JOIN question_translation qt ON q.id = qt.question_id WHERE qt.language = 'en'

В Java с помощью JPA КРИТЕРИИ это выглядит следующим образом:

@Override 
public Collection<Question> findByMonthYear(String month, String year, String locale) { 
    EntityManager em = sessionFactory.createEntityManager(); 
    CriteriaBuilder builder = em.getCriteriaBuilder(); 
    CriteriaQuery<Question> criteriaQuery = builder.createQuery(Question.class); 

    List<Predicate> predicates = new ArrayList<>(); 

    Root<Question> questionRoot = criteriaQuery.from(Question.class); 
    ListJoin<Question, QuestionTranslation> questionTranslationJoinRoot = questionRoot.join(Question_.questionTranslation, JoinType.LEFT); 

    predicates.add(builder.equal(questionRoot.get(Question_.month), month)); 
    predicates.add(builder.equal(questionRoot.get(Question_.year), year)); 
    predicates.add(builder.equal(questionTranslationJoinRoot.get(QuestionTranslation_.language), locale)); 

    criteriaQuery.select(questionRoot).where(predicates.toArray(new Predicate[]{})); 

    TypedQuery<Question> query = em.createQuery(criteriaQuery); 

    String queryString = query.unwrap(Query.class).getQueryString(); 

    return query.getResultList(); 
} 

Я использую ListJoin, потому что в метамодели Question_.class я получил эту строку:

public static volatile ListAttribute<Question, QuestionTranslation> questionTranslation; 

Но этот возвращает мне класс вопросов со списком QuestionTranslation с двумя записями, где поле языка равно en и de. Но я указываю, где предложение возвращает мне только одну запись, где язык равен en. Что случилось с моим кодом?

UPDATE # 1:

У меня второй случай.

еще одна таблица:

CREATE TABLE public.user_answer 
(
    uuid  VARCHAR(36) PRIMARY KEY 
    , user_uuid VARCHAR(36) REFERENCES public.users(uuid) NOT NULL 
    , question_id INT   REFERENCES public.question(id) NOT NULL 
    , answer  TEXT          NOT NULL 
); 

И я хочу, чтобы сделать SQL, как это:

SELECT * FROM user_answer ua LEFT JOIN question q on ua.question_id = q.id LEFT JOIN question_translation qt ON q.id = qt.question_id WHERE qt.language = 'en' AND ua.user_uuid = '00000000-user-0000-0000-000000000001' AND q.month = '01' AND q.day = '01' AND q.year = '2016';

В Java с помощью JPA КРИТЕРИИ это выглядит следующим образом:

@Override 
public UserAnswer findByDayMonthYear(String day, String month, String year, User user, String locale) { 
    EntityManager em = sessionFactory.createEntityManager(); 
    CriteriaBuilder builder = em.getCriteriaBuilder(); 
    CriteriaQuery<UserAnswer> criteriaQuery = builder.createQuery(UserAnswer.class); 

    List<Predicate> predicates = new ArrayList<>(); 

    Root<UserAnswer> userAnswerRoot = criteriaQuery.from(UserAnswer.class); 
    Join<UserAnswer, Question> questionJoin = userAnswerRoot.join(UserAnswer_.question); 
    ListJoin<Question, QuestionTranslation> questionTranslatJoin = questionJoin.join(Question_.questionTranslation); 

    predicates.add(builder.equal(builder.treat(questionJoin, Question.class).get(Question_.day), day)); 
    predicates.add(builder.equal(builder.treat(questionJoin, Question.class).get(Question_.month), month)); 
    predicates.add(builder.equal(builder.treat(questionJoin, Question.class).get(Question_.year), year)); 
    predicates.add(builder.equal(builder.treat(questionTranslatJoin, QuestionTranslation.class).get(QuestionTranslation_.language), locale)); 
    predicates.add(builder.equal(userAnswerRoot.get(UserAnswer_.user), user)); 

    criteriaQuery.select(userAnswerRoot).where(predicates.toArray(new Predicate[]{})); 

    TypedQuery<UserAnswer> query = em.createQuery(criteriaQuery); 

    String queryString = query.unwrap(Query.class).getQueryString(); 

    return query.getSingleResult(); 
} 

В этом случае у Вопроса есть Список с двумя пунктами QuestionTranlsation с языком es en и de, но мне нужна только одна запись QuestionTranlsation, где язык равен en.

Что мне нужно делать в этом случае?

ответ

2

Это возможно с JPA 2.1 особенность JOIN ON

см How to do JOIN ON query using Criteria API

+0

посмотрите мое обновление вопрос пожалуйста. – dikkini

+0

Зачем мне это нужно? Вы можете получить доступ к «Вопросу перевода». –

+0

Я использую JPA 2.1, дайте мне совет, как использовать «JOIN ON language»? – dikkini

Смежные вопросы