【问题标题】:Spring data REST findBy nested entitySpring data REST findBy 嵌套实体
【发布时间】:2018-05-28 07:46:02
【问题描述】:

我有一个使用 Spring-data-rest 生成我的 REST 接口的 Spring Boot 项目,我正在尝试允许对嵌套资源进行分页。我遵循了这个workaround 并坚持实施 findBy 查询。

我有以下设备实体:

@Entity
@Table(name = "devices")
public class Device extends ResourceSupport {

  ...

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "user_id")
  private User user;
}

我需要使用 userId 来查询它:

@RequestMapping(path = "/users/{id}/devices", method = RequestMethod.GET)
public ModelAndView getUserDevices(@PathVariable Integer id) {
    return new ModelAndView("forward:/devices/search/findByUserId?userId=" + id);
}

所以我在我的 DeviceRepository 中创建了以下方法:

@Repository
public interface DeviceRepository extends JpaRepository<Device, Long> {

  @PreAuthorize("hasRole('ROLE_ADMIN') OR @securityCheck.check(#user, authentication)")
  Page<Device> findByUserId(@Param("user") User user, Pageable pageable);

}

但我在尝试向此端点发送请求时遇到以下异常:

Unable to locate Attribute  with the the given name [id] on this ManagedType [com.example.User]

有没有人建议我做错了什么?

编辑: 谢谢你的回复,我把方法改成了

Page<Device> findByUser_UserId(@Param("user") User user, Pageable pageable);

我的用户实体包含一个userId 字段。

但是,现在我遇到了以下异常:

{
    "cause": {
        "cause": {
            "cause": null,
            "message": "Cannot resolve URI 1. Is it local or remote? Only local URIs are resolvable."
        },
        "message": "Failed to convert from type [java.net.URI] to type [@org.springframework.data.repository.query.Param com.example.User] for value '1'; nested exception is java.lang.IllegalArgumentException: Cannot resolve URI 1. Is it local or remote? Only local URIs are resolvable."
    },
    "message": "Failed to convert 1 into me.originalsin.user.model.User!"
}

看来我用错了查询?

【问题讨论】:

    标签: java spring-boot spring-data-rest


    【解决方案1】:

    试试

     Page<Device> findByUser_Id(@Param("user") User user, Pageable pageable);
    

    由于您在 DeviceRepository 中创建了一个方法,并且您想搜索一个嵌套的字段(user.id),您需要使用“_”来引用它

    【讨论】:

      【解决方案2】:

      请查看docs

      属性表达式只能引用托管实体的直接属性,如前面的示例所示。在创建查询时,您已经确保解析的属性是托管域类的属性。但是,您也可以通过遍历嵌套属性来定义约束。假设一个人有一个带有邮政编码的地址。在这种情况下,方法名称为

      List<Person> findByAddressZipCode(ZipCode zipCode);
      

      [...] 虽然这应该适用于大多数情况,但算法可能会选择错误的属性。假设 Person 类也有一个 addressZip 属性。该算法已经在第一个拆分轮中匹配,并且基本上选择了错误的属性并最终失败(因为 addressZip 的类型可能没有 code 属性)。 要解决这种歧义,您可以在方法名称中使用 _ 来手动定义遍历点。所以我们的方法名最终会是这样的:

      List<Person> findByAddress_ZipCode(ZipCode zipCode);
      

      这意味着:你所做的应该可以工作,除非你的 Device 类有一个字段 userId

      您向我们展示的例外是原始问题中的以下内容。

      无法在此 ManagedType [com.example.User] 上找到具有给定名称 [id] 的属性

      这看起来您的班级User 没有名为id 的字段。由于您没有向我们展示此类的代码,因此我无法判断是否是这种情况。 (确保您在存储库中导入了正确的 User 类)

      问题已更新,因此另一个答案存在另一个错误

      现在的问题是您将 User 对象传递给您的存储库方法,但通过 id 进行过滤。只需将第一个参数更改为用户 ID 的数据类型。我认为这应该有效。

      假设 id 的类型是 int,该方法可能如下所示

      Page<Device> findByUser_UserId(@Param("userId") int userId, Pageable pageable);
      

      【讨论】:

      • 感谢您的回答,这对我帮助很大。但我得到了完全不同的例外。请您看一下更新后的问题吗?
      猜你喜欢
      • 1970-01-01
      • 2018-05-28
      • 2014-08-25
      • 1970-01-01
      • 2012-09-25
      • 1970-01-01
      • 2019-09-13
      • 2014-06-05
      相关资源
      最近更新 更多