需要在JPA存储库中询问查询。我有像这样映射的实体
private String name;
private Set<String> roles;
有两个不同的字符串角色" users“和" managers”需要分别列出所有用户和所有尝试过的经理
findAllByRolesContains(String role);
然后尝试:
return userRepository.findAllByRolesContains("users");
接收到的响应
参数值%users%与预期类型不匹配
我该怎么问才对呢?已尝试
findAllByInRolesContains(String role);
它根本不起作用。
发布于 2021-09-12 12:07:13
因此,首先,我看到您的问题中没有添加"spring“和"spring data jpa”的标记。我想提醒您,您展示的是Spring Data JPA的代码片段--这是构建在Java Persistence API (JPA)之上的Spring框架的一部分。确保您首先理解了基础知识(JPA)!Spring Data在幕后构建了JPA查询,并自动化了许多东西,但它并不能让您了解如何使用JPA!
接下来,如果您有特定的角色,即不是任意字符串("role1324"),那么您可能希望改为使用map an Enum。
但让我们看看你的案例:
@Entity
public class User {
@Id
private String name;
@ElementCollection
private Set<String> roles;
}
因此,您正在尝试为您的存储库创建一个查询方法-- Spring Data根据该方法的名称生成查询。这些规则可以在reference documentation中找到。
那么findAllByRolesContains
会生成什么呢?“find”和“By”之间的任何内容都是描述性的,即被忽略。“‘Roles”是属性,“Contains”可能表示“包含在集合中”或“包含在字符串中”。但是我们这里缺少一个级别-您想要检查集合中的字符串是否包含某些内容。我还没有找到一种方法来告诉Spring Data创建正确的查询。findAllByRolesLike
是最接近的一个,但是你必须手动地用‘%’来包装搜索字符串。获取Spring数据来创建正确的查询可能是变化无常的,如果它不是直接的,那就是浪费时间。你总是可以自己编写查询:
@Query("select user from User user join user.roles role where role like %:role%")
List<User> findAllByRolesContaining(@Param("role") String role);
但是,如果您使用角色为“管理员”、“管理员”的用户进行测试,则会得到相同的用户两次?!怎么回事?!嗯,这就是底层SQL的工作方式-它过滤行,有两行"username - admin“和"username - administrator”。你想要分心的关键字来过滤掉它们:
@Query("select distinct user from User user join user.roles role where role like %:role%")
List<User> findAllByRolesContaining(@Param("role") String role);
还有一个优化:如果角色是一个@ElementCollection
,那么默认情况下它们是延迟获取的。如果您知道需要访问它,可以在join
之前添加一个join fetch user.roles
。这将急切地加载它。如果你愿意,你可以创建两种不同的方法。如果您不需要它们,那么您希望避免获取它们,但是如果您知道您将需要它们,那么延迟加载可能会发出多个查询。
wikibook on JPA是一个很好的资源,Vlad Mihalcea的书和博客是你能找到的关于高性能JPA的最好的资源。还有-不要太依赖Spring Data JPA的自动魔力,我想除了最琐碎的查询之外,它对任何事情都弊大于利……
https://stackoverflow.com/questions/69133116
复制相似问题