Spring Boot 3.x.x,带条件的左连接停止正常工作

问题描述 投票:0回答:1

我在 jpa 存储库中有自定义查询:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    @Query("""
        select 
            user
        from User user
        left join user.role r
        left join r.attributes a on a.type = '2'
        where user.id = :userId
    """)
    @EntityGraph("User.getRoles")
    User getMyUser(@Param("userId") Long userId);
}

实体

@Entity(name = "users")
@NamedEntityGraph(name = "User.getRoles", attributeNodes = {
            @NamedAttributeNode(value = "role", subgraph = "User.getRoles.attributes")
        },
        subgraphs = {
                @NamedSubgraph(name = "User.getRoles.attributes",
                        attributeNodes = @NamedAttributeNode(value = "attributes")
                )
        }
)
public class User {
    @Id
    @GeneratedValue
    private Long id;
    @ManyToMany
    @JoinTable(
            name = "user_roles",
            joinColumns = @JoinColumn(name = "user_id"),
            inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> role;
}

@Entity
public class Role {
    @Id
    @GeneratedValue()
    private Long id;
    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "attribute_id")
    public Set<Attribute> attributes;
}

@Entity
public class Attribute {
    @Id
    @GeneratedValue
    private Long id;
    @ManyToOne
    @JoinColumn(name = "role_id")
    private Role role;
    private String type;
}

当我使用 Spring Boot 2.6.4 时,我的 Hibernate 查询是:

select
        user0_.id as id1_3_0_,
        role2_.id as id1_1_1_,
        attributes3_.id as id1_0_2_,
        role1_.user_id as user_id1_2_0__,
        role1_.role_id as role_id2_2_0__,
        attributes3_.role_id as role_id3_0_2_,
        attributes3_.type as type2_0_2_,
        attributes3_.attribute_id as attribut4_0_1__,
        attributes3_.id as id1_0_1__ 
    from
        users user0_ 
    left outer join
        user_roles role1_ 
            on user0_.id=role1_.user_id 
    left outer join
        roles role2_ 
            on role1_.role_id=role2_.id 
    left outer join
        attribute attributes3_ 
            on role2_.id=attributes3_.attribute_id 
            and (
                attributes3_.type='2'
            ) 
    where
        user0_.id=?

当我使用 Spring Boot 3.0.0 Hibernate 查询时:

Hibernate: 
    select
        u1_0.id,
        r2_0.user_id,
        r2_1.id,
        a2_0.attribute_id,
        a2_0.id,
        a2_0.role_id,
        a2_0.type 
    from
        users u1_0 
    left join
        (user_roles r1_0 
    join
        roles r1_1 
            on r1_1.id=r1_0.role_id) 
                on u1_0.id=r1_0.user_id 
        left join
            attribute a1_0 
                on r1_1.id=a1_0.attribute_id 
                and a1_0.type='2' 
        left join
            (user_roles r2_0 
        join
            roles r2_1 
                on r2_1.id=r2_0.role_id) 
                    on u1_0.id=r2_0.user_id 
            left join
                attribute a2_0 
                    on r2_1.id=a2_0.attribute_id 
            where
                u1_0.id=?

但真正的问题是不同的结果:

    public User method() {
        var myUser = userRepository.getMyUser(1L);
        System.out.println(myUser);
        return myUser;
    }

Spring Boot 2.6.4:

User(id=1, role=[Role(id=1, attributes=[Attribute(id=2, type=1)])])

Spring Boot 3.0.0:

User(id=1, role=[Role(id=1, attributes=[Attribute(id=2, type=1), Attribute(id=1, type=2)])])

我也无法将条件从 ON 移动到 WHERE,因为左连接将用作内连接。 这不行:

        select 
            user
        from User user
        left join user.role r
        left join r.attributes a 
        where user.id = :userId and (a.type = '2' or a.type is null)

我想使用 springboot 3.2.0 并让查询正常工作

spring-boot hibernate jpa spring-data-jpa jpql
1个回答
0
投票

似乎 Hibernate 从版本 6 开始工作方式有所不同: https://hibernate.atlassian.net/browse/HHH-15612

© www.soinside.com 2019 - 2024. All rights reserved.