java - Hibernate @ManyToMany 不使用 joinTable 并生成笛卡尔而不是内连接

标签 java hibernate jpa many-to-many

同事们,当关系 @ManyToMany 时,您能否就 Hibernate 问题向我提出建议。 项目单位:

    @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);

我预计只会得到一个 Project#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'}

当我检查 Hibernate 生成的 SQL(属性 hibernate.show_sql = true)时,我注意到 Hibernate 创建连接表“PROJECT”和“EMPLOYEE”而不使用中间表“EMPLOYEE_PROJECTS”(请参阅​​ Project 类中的注释 @JoinTable) 。生成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 仅选择一个/多个员工的外部属性值= false 的项目? pom.xml:

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

最佳答案

问题来自您的 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

关于java - Hibernate @ManyToMany 不使用 joinTable 并生成笛卡尔而不是内连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50282293/

相关文章:

java - ManyToManyToMany - 使用 Hibernate 注释连接三个表

java - 选项标记中的 mysql 列值

java - 为什么将 k-ary 树表示为左子树、右兄弟树?

java - org.springframework.beans.factory.BeanCreationException : Error creating bean

hibernate - 域模型对象在层之间传递开销吗?

java - 在不同的事务问题中保持相同的依赖关系

java - 我已经使用了 SelectBeforeUpdate 但每次我坚持一个分离的对象而不进行任何更改时, hibernate 都会使用带有 null 的列值进行保存

java - 如何指定通用类型作为函数参数

java - 如何修复无效的 infinispan 数据存储?

java - 更多决策表在流口水