Hibernate @ManyToMany не использует joinTable и производит декартову вместо внутреннего соединения - PullRequest
0 голосов
/ 11 мая 2018

Коллеги, не могли бы вы посоветовать мне вопросы Hibernate, когда отношения @ManyToMany. Объект проекта:

    @Entity
    @Table(name = "PROJECT")
    @NamedQueries( {
        @NamedQuery(name = "Projects.employeesByExternal", query = "SELECT P FROM Project P INNER JOIN Employee E ON E.external=:external" )
    } )
    public class Project extends AbstractIdentified
    {
        @Column(name = "NAME") private String name;
        @Column(name = "EXT") private Boolean external;

        @ManyToMany
        @JoinTable( name = "EMPLOYEE_PROJECTS",
        joinColumns = { @JoinColumn(name = "PROJECT_ID") },
        inverseJoinColumns = { @JoinColumn(name = "EMPLOYEE_ID") } )
        private Set<Employee> employees;
    ... 
    // getters/setters here
    }

Субъект работника:

    @Entity
    @Table(name = "EMPLOYEE")
    public class Employee extends AbstractIdentified
    {
        @ManyToMany(mappedBy = "employees")
        private Set<Project> projects;
        ....
        // other fields and getters/setters here
    }

Когда приложение запускается, оно запускает init.sql:

insert into employee (id,status,ext) values (1,'CORP',true);
insert into employee (id,status,ext) values (2,'CORP',false);
insert into employee (id,status,ext) values (3, 'EXT',true);
insert into project (id,name) values (1,'project1');
insert into project (id,name) values (2,'project2');
insert into project (id,name) values (3,'project3');
insert into employee_projects (employee_id, project_id) values (1,1);
insert into employee_projects (employee_id, project_id) values (2,2);
insert into employee_projects (employee_id, project_id) values (3,3);

В DAO я подготовил метод DAO для выбора проекта, в котором сотрудник (по крайней мере, один) имеет external = false:

public List<Project> getProjectsByExternal( boolean isExternal )
{
    TypedQuery<Project> typedQuery = entityManager.createNamedQuery( "Projects.employeesByExternal", Project.class );
    typedQuery.setParameter( "external", isExternal );
    return typedQuery.getResultList();
}

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

List<Project> list = projectDao.getProjectsByExternal(false);

И я ожидаю получить только один Проект # 2 {name = 'project2'}, но в результате получится 3 проекта:

01:03:49 INFO  vez.Starter - Project#1{name='project1'}
01:03:49 INFO  vez.Starter - Project#2{name='project2'}
01:03:49 INFO  vez.Starter - Project#3{name='project3'}

Когда я проверял, какой SQL был сгенерирован Hibernate (свойство hibernate.show_sql = true), я заметил, что Hibernate создает таблицы соединения "PROJECT" и "EMPLOYEE" без использования промежуточной таблицы "EMPLOYEE_PROJECTS" (см. Аннотацию @JoinTable в классе Project) , Сгенерирован SQL:

01:03:49 DEBUG org.hibernate.SQL - 
    select
        project0_.ID as ID1_3_,
        project0_.NAME as NAME2_3_ 
    from
        PROJECT project0_ 
    inner join
        EMPLOYEE employee1_ 
            on ( employee1_.EXT=?)

На самом деле это означает, что один Сотрудник был выбран и умножен для всех Проектов. Я озадачен, потому что это декартово, но не внутреннее соединение, которое я ожидал. Посоветуйте пожалуйста, что я сделал не так? Как я могу использовать NativeQuery для выбора только проектов с одним или несколькими сотрудниками, имеющими внешний атрибут value = false? pom.xml:

<spring.version>5.0.5.RELEASE</spring.version>
<hibername.version>5.3.0.CR2</hibername.version>

1 Ответ

0 голосов
/ 11 мая 2018

Проблема связана с вашим запросом JPQL:

SELECT P FROM Project P INNER JOIN Employee E ON E.external=:external

Вы должны изменить его на:

SELECT P 
FROM Project P 
INNER JOIN P.employees E 
Where E.external=:external
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...