我有这样的数据库结构:
topics 1:n posts 1:n comments and users n:n roles.
我想获得用户有权访问的所有评论。
为我提供访问权限意味着(当我创建post对象时,我自动创建名为PostName的角色对象,前缀为role_comment_,例如名为abc的帖子,其角色名为:role_comment_abc)
现在我尝试创建如下的jpa / jpql查询:
find all comments by User where user_id is =:1 and role_name contaings =:2
findByUserIdAndRoleNameContaining(Integer userId, String roleName);
这就是我的用户,角色和评论表的样子:
角色表:
@Entity
@Table(name = "roles")
public class Role {
@Id
private Integer id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users = new HashSet<>();
用户和user_role表:
@Entity
@Table(name = "users")
public class User {
@Id
private Integer id;
private String name;
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
@JoinTable(
name = "user_role",
joinColumns = { @JoinColumn(name = "user_id") },
inverseJoinColumns = { @JoinColumn(name = "role_id") }
)
private Set<Role> roles = new HashSet<>();
这是评论表:
@Entity
@Table(name = "comments")
public class Comments{
@Id
private Integer id;
private String name;
private String description;
@ManyToOne(optional = false)
@JoinColumn(nullable = false, name = "user_id")
private User user
如果我在JpaRepository中创建一个名为:
的查询,那就太不方便了List<Comments> findByUserId(Integer id);
如果我没错,它会打印该特定用户创建的评论。
那么我真正想要实现的目标是什么?让我在示例数据上向您展示:
作用:
100;"role_comment_ab"
101;"role_comment_cd"
102;"role_comment_ef"
103;"something_else"
名称为ab的帖子中的评论:
1;"Test1";"Test description";10
2;"Test2";"Test description";10
在帖子中注释名称为cd:
3;"Test3";"Test description";10
4;"Test4";"Test description";10
帖子中的评论名称为ef:
5;"Test5";"Test description";10
6;"Test6";"Test description";10
用户:
10;"Thomas" (logged user)
11;"John"
users_roles:
10;100
11;101
10;102
10;103
输入:
findByUserIdAndRoleNameContaining(10, "role_comment_");
输出:
1;"Test1";"Test description";10
2;"Test2";"Test description";10
5;"Test5";"Test description";10
6;"Test6";"Test description";10
我真的不知道我的查询应该是什么样子。至少至少给我一点暗示。
更新: 添加@Bohdan Petrenko解决方案后:
@Query("select c from Comment c join c.user u join u.roles r where u.id = :userId and lower(r.name) like lower(:roleName)")
List<Comment> findByUserIdAndRoleNameContaining(@Param("userId") Integer userId, @Param("roleName") String roleName);
roleName = "%" + roleName.trim() + "%";
我注意到,如果@Param roleName包含“roleName”字符串,此解决方案将打印所有注释。
所以如果我有role_postName1和role_postName2 它打印:
comment1FromPost1
comment2FromPost1
comment1FromPost2
comment2FromPost2
comment1FromPost1
comment2FromPost1
comment1FromPost2
comment2FromPost2
只有当用户拥有名为role_postName的角色时,才能找到从帖子打印评论的解决方案。
答案 0 :(得分:1)
@Query("select t from Topic t
join t.user u
where u.id = :userId
and u.roles in :roleNames")
List<Topic> findByUserIdAndRoleNameContainedIn(@Param("userId") Integer userId, @Param("roleNames") List<String> roleNames);
答案 1 :(得分:0)
请在您的问题中更具体。
如果我理解正确 - 您希望按用户ID和角色名称选择主题。如果是,您可以尝试这样的事情:
@Query("select t from Topic t join t.user u join u.roles r where u.id = :userId and lower(r.name) like lower(:roleName)")
List<Topic> findByUserIdAndRoleNameContaining(@Param("userId") Integer userId, @Param("roleName") roleName);
但是在将角色名称传递给存储库方法findByUserIdAndRoleNameContaining
之前,您还需要更改角色名称:
roleName = "%" + roleName.trim() + "%";
<强>更新强>
这将无需任何自定义SQL和roleName
修改
List<Comment> findByUser_IdAndUser_Roles_NameContainingIgnoreCase(Integer userId, String roleName);
而且我也不明白你现在面临的麻烦。因此,为我们提供一些测试数据(来自数据库)的示例,查询的正确和错误的预期结果。由于我不明白你问题的原因,我无法帮助你解决它。