我在 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 并让查询正常工作
似乎 Hibernate 从版本 6 开始工作方式有所不同: https://hibernate.atlassian.net/browse/HHH-15612