Коллеги, не могли бы вы посоветовать мне вопросы 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>