【发布时间】:2018-07-14 13:56:00
【问题描述】:
我有一个这样的数据库结构:
topics 1:n posts 1:n comments and users n:n roles.
我想获取该用户有权访问的所有 cmets。
为我授予访问权限意味着(当我创建帖子对象时,我会自动创建名为 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<>();
用户和用户角色表:
@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<>();
这是 cmets 表:
@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);
如果我没记错的话,它将打印由该特定用户创建的 cmets。
那么我真正想要达到的目标是什么?让我通过示例数据向您展示这一点:
角色:
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
cmets 在帖子中名为 cd:
3;"Test3";"Test description";10
4;"Test4";"Test description";10
cmets 在帖子中名为 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”字符串,此解决方案将打印所有 cmets。
如果我有 role_postName1 和 role_postName2 它打印:
comment1FromPost1
comment2FromPost1
comment1FromPost2
comment2FromPost2
comment1FromPost1
comment2FromPost1
comment1FromPost2
comment2FromPost2
只有当用户具有名为 role_postName 的角色时,才能找到从帖子中打印 cmets 的解决方案。
【问题讨论】:
-
你试过
findByUser_IdAndUser_Roles_Name(Integer userId, String roleName) -
您的解决方案给了我一个错误:调用 init 方法失败;嵌套异常是 java.lang.IllegalStateException:非法尝试取消引用基本类型的路径源 [null.user.roles]
-
@pvpkiran 你知道为什么会出现这个问题吗?
-
因为角色是一个集合。我认为您需要使用元素并查看该角色是否存在于该用户的角色集中。在这里查看我的答案stackoverflow.com/questions/48424575/…
标签: java spring spring-data spring-data-jpa jpql