JPA加入特定领域

s1m*_*r3d 5 java hibernate specifications jpa join

我有这样的场景:

User及其相关的UserRole实体类,如下:

@Entity
@Table(name="USER")
public class User implements Serializable {

   @Id
   @GeneratedValue(strategy=GenerationType.AUTO)
   @Column(name="ID", unique=true, nullable=false)
   private int id;

   @Column(name="USERNAME", unique=true, nullable=false, length=255)
   private String username;

   @OneToMany(mappedBy="user")
   private List<UserRole> userRoles;
}
Run Code Online (Sandbox Code Playgroud)

@Entity
@Table(name="user_roles")
public class UserRole implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name="user_role_id", unique=true, nullable=false)
    private int userRoleId;

    @Column(nullable=false, length=45)
    private String role;

    @ManyToOne
    @JoinColumn(name="username", nullable=false)
    private User user;
}
Run Code Online (Sandbox Code Playgroud)

现在,我需要查询具有特定角色的所有用户。我正在尝试使用 JPA 规范进行连接,如下所示:

Join<User, UserRole> join = root.join(User_.userRoles);
Expression<String> match = join.get(UserRole_.role);                    
Predicate predicate = builder.equal(match, "ROLE_USER");
Run Code Online (Sandbox Code Playgroud)

问题是生成的联接将在 User 之间进行。id和用户角色。用户名和查询显然不会有结果。

select count(user0_.ID) as col_0_0_ from USER user0_ inner join
user_roles userroles1_ on user0_.ID=userroles1_.username where 
userroles1_.role='ROLE_USER'
Run Code Online (Sandbox Code Playgroud)

我需要在用户名字段上都有 on 子句:

... from USER user0_ inner join
    user_roles userroles1_ on user0_.USERNAME=userroles1_.username ...
Run Code Online (Sandbox Code Playgroud)

我注意到Join 类有.on方法:

修改连接以根据指定的 ON 条件限制结果。替换之前的 ON 条件(如果有)。返回连接对象

这是正确的方法吗?如果是这样,我该如何实施?

Join<User, UserRole> join = root.join(User_.userRoles).on(????);
Run Code Online (Sandbox Code Playgroud)

先感谢您。

更新UserRole_元模型类

@StaticMetamodel(UserRole.class)
public class UserRole_ {
    public static volatile SingularAttribute<UserRole, Integer> userRoleId;
    public static volatile SingularAttribute<UserRole, String> role;
    public static volatile SingularAttribute<UserRole, User> user;
}
Run Code Online (Sandbox Code Playgroud)

User_元模型类:

@StaticMetamodel(User.class)
public class User_ {
    public static volatile SingularAttribute<User, Integer> id;
    public static volatile SingularAttribute<User, String> username;
    public static volatile ListAttribute<User, UserRole> userRoles;
}
Run Code Online (Sandbox Code Playgroud)

Tob*_*fke 5

您需要使用referencedColumnName

@ManyToOne
@JoinColumn(name="username", referencedColumnName="username", nullable=false)
private User user;
Run Code Online (Sandbox Code Playgroud)

只有@JoinColumn(name="username")您告诉 Hibernate 中的连接列user_roles已命名username- 但它仍然期望它包含 User 属性的值@Id。如果您为架构创建 DDL,您将看到 Hibernate 为 生成一个数字列user_roles.username