2013-06-12 2 views
1

Я использую Querydsl 2.9, Spring Data JPA 1.3.0 и Hibernate JPA 2 API версии 1.0. Я пытаюсь сделать простое соединение между двумя таблицами: Parent и Child, присоединившись к столбцу parentId. По какой-то причине запрос, который выполняется Hibernate, всегда содержит дополнительный cross join. Таблицы выглядеть следующим образом:Extra Cross Присоединиться к данным Spring JPA & Querydsl

CREATE TABLE PARENT (
    PARENTID INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    NAME VARCHAR(255) 
); 

CREATE TABLE CHILD (
    CHILDID INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    PARENTID INT(11), 
    NAME VARCHAR(255) 
); 

Классы домена выглядеть следующим образом:

@Entity 
@Table(name="PARENT") 
public class Parent { 

    @Id 
    @GeneratedValue 
    private Integer parentId; 

    private String name; 

    @OneToMany 
    @JoinColumn(name="parentId") 
    private List<Child> children; 

    // ... getters/setters omitted for brevity 
} 

@Entity 
@Table(name="CHILD") 
public class Child { 

    @Id 
    @GeneratedValue 
    private Integer childId; 

    private Integer parentId; 

    private String name; 

    // ... getters/setters omitted for brevity 
} 

Мой код запроса выглядит следующим образом:

private List<Parent> test(List<Integer> parentIds) { 
    JPAQuery query = new JPAQuery(entityManagerFactory.createEntityManager()); 
    QParent qParent = QParent.parent; 
    QChild qChild = QChild.child; 

    List<Parent> parents = query.from(qParent, qChild) 
     .innerJoin(qParent.children, qChild) 
     .where(qParent.parentId.in(parentIds)) 
     .list(qParent); 

     return parents; 
} 

Я ожидал бы сгенерированный запрос выглядеть например:

select 
    p.parentId, p.name 
from 
    parent p 
     inner join 
    child c on c.parentid = p.parentid 
where 
    p.parentid in(1, 2); 

Однако запрос, который на самом деле запустить это:

select 
    parent0_.parentId as parentId1_3_, parent0_.name as name2_3_ 
from 
    PARENT parent0_ 
     inner join 
    CHILD children2_ ON parent0_.parentId = children2_.parentId 
     cross join 
    CHILD child1_ 
where 
    parent0_.parentId in (1 , 2); 

Обратите внимание на дополнительные cross join в конце. Я понимаю, что могу получить правильные результаты, если я сделаю group by по адресу childId, но я не хочу лишних накладных расходов cross join, когда это не обязательно. Я пробовал использовать как innerJoin, так и join безрезультатно. Я просмотрел документы Querydsl, и я вижу, что тип соединения по умолчанию - это перекрестное соединение, поэтому, возможно, я не правильно определяю свое соединение? Как я могу избавиться от дополнительного кросс-соединения?

ответ

1

Второй из аргументов, вероятно, отвечает за перекрестное соединение.

Попробуйте вместо

List<Parent> parents = query.from(qParent) 
    .innerJoin(qParent.children, qChild) 
    .where(qParent.parentId.in(parentIds)) 
    .list(qParent); 
Смежные вопросы