【问题标题】:Spring Data REST @Idclass not recognizedSpring Data REST @Idclass 无法识别
【发布时间】:2015-10-27 06:46:35
【问题描述】:

我有一个名为 EmployeeDepartment 的实体,如下所示

@IdClass(EmployeeDepartmentPK.class) //EmployeeDepartmentPK is a serializeable object
@Entity
EmployeeDepartment{

@Id
private String employeeID;

@Id
private String departmentCode;
---- Getters, Setters and other props/columns
}

我有一个如下定义的 Spring Data Repository

@RepositoryRestResource(....)
public interface IEmployeeDepartmentRepository extends PagingAndSortingRepository<EmployeeDepartment, EmployeeDepartmentPK> {

}

此外,我注册了一个转换器,可以从 String 转换为 EmployeeDepartmentPK。

现在,对于一个由 ID employeeID="abc123" 和 departmentCode="JBG" 限定的实体,我希望在调用 SDR 接口时使用的 ID 是 abc123_JBG。 例如,http://localhost/EmployeeDepartment/abc123_JBG 应该为我获取结果,并且确实如此。

但是,当我尝试使用 PUT 保存实体时,Spring Data Commons 的 BasicPersistentEntity 类中可用的 ID 属性值为 部门代码的 abc123_JBG。这是错误的。我不确定这是否是预期的行为。

请帮忙。

谢谢!

【问题讨论】:

    标签: spring hibernate jpa spring-data spring-data-rest


    【解决方案1】:

    目前 Spring Data REST 仅支持由单个字段表示的复合键。这实际上意味着只支持@EmbeddedId。我已经提交了DATAJPA-770 来解决这个问题。

    如果您可以切换到@EmbeddedId,您仍然需要教 Spring Data REST 以您希望在 URI 中表示复杂标识符的方式以及如何将路径段转换回您的 id 类型的实例。为此,请实现 BackendIdConverter 并将其注册为 Spring bean。

    @Component
    class CustomBackendIdConverter implements BackendIdConverter {
    
      @Override
      public Serializable fromRequestId(String id, Class<?> entityType) {
    
        // Make sure you validate the input
    
        String[] parts = id.split("_");
        return new YourEmbeddedIdType(parts[0], parts[1]);
      }
    
      @Override
      public String toRequestId(Serializable source, Class<?> entityType) {
    
        YourIdType id = (YourIdType) source;
        return String.format("%s_%s", …);
      }
    
      @Override
      public boolean supports(Class<?> type) {
        return YourDomainType.class.equals(type);
      }
    }
    

    【讨论】:

    • 我遵循这个建议只是为了偶然发现如何通过发布请求创建一个 embeddedId。见:stackoverflow.com/questions/36606251/…
    • 即使将实体添加到 config.exposeIdsFor() 方法后,复合键列 (EmbeddedId) 也不会公开。
    • 事实证明你可以,只要嵌入的 id 的属性名称为“Id”。它也嵌套了id : { "column1": "val1", "column2": "val2" }
    【解决方案2】:

    如果您不能使用@EmbeddedId,您仍然可以使用@IdClass。为此,您需要 Oliver Gierke 回答的 BackendIdConverter,但您还需要为您的域类型添加查找:

    @Configuration
    public class IdClassAllowingConfig extends RepositoryRestConfigurerAdapter {
    
    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.withEntityLookup().forRepository(EmployeeDepartmentRepository.class, (EmployeeDepartment ed) -> {
            EmployeeDepartmentPK pk = new EmployeeDepartmentPK();
            pk.setDepartmentId(ed.getDepartmentId());
            pk.setEmployeeId(ed.getEmployeeId());
            return pk;
        }, EmployeeDepartmentRepository::findOne);
    }
    

    }

    【讨论】:

    • 感谢您。使用这个,我可以不嵌套 id 列。
    • 对我来说,fineOne 导致“没有为类 org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor 找到序列化程序”异常。使用findById 修复相同。
    【解决方案3】:

    使用@BasePathAwareController自定义Spring数据休息控制器。

        @BasePathAwareController
        public class CustInfoCustAcctController {
    
        @Autowired
        CustInfoCustAcctRepository cicaRepo;
    
        @RequestMapping(value = "/custInfoCustAccts/{id}", method = RequestMethod.GET)
        public @ResponseBody custInfoCustAccts getOne(@PathVariable("id") String id) {
            String[] parts = id.split("_");
            CustInfoCustAcctKey key = new CustInfoCustAcctKey(parts[0],parts[1]);
            return cicaRepo.getOne(key);
        }
    }
    

    示例 uri /api/custInfoCustAccts/89232_70 对我来说很好

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-03
      • 2019-01-23
      • 2014-02-18
      • 2020-08-20
      • 2021-08-28
      • 1970-01-01
      • 2016-10-26
      • 2019-04-16
      相关资源
      最近更新 更多