1

我正在使用 Spring Boot (2.1.1) 自动创建我的JpaRepository接口的 HAL REST API。

在大多数情况下,这些接口是空的,例如:

public interface ProjectRepository extends JpaRepository<Project, Long> {}

public interface ProtocolRepository extends JpaRepository<Protocol, Long> {}

一个实体Project包含许多Protocol实体。并且Protocol-entity 具有到它的Project-entity 的反向链接。

当我访问时,http://localhost:8080/admin/protocols/4711我得到了它的项目的链接:

...
"project": {
  "href": "http://localhost:8080/admin/protocols/4711/project"
}
...

但是当我点击该链接时,所有进一步的链接都生成错误:

  ...
  "_links": {
    "self": {
      "href": "http://localhost:8080/admin/project/1"
    },
    "project": {
      "href": "http://localhost:8080/admin/project/1"
    }
  ...
  }
  ...

链接中的错误是使用了单数名词project,而不是复数形式projects

由于这些链接是自动生成的,因此如何更改此行为并不明显。

4

1 回答 1

1

在调试 Spring 内部时,我发现它PersistentEntityResourceAssembler使用一个实例DefaultSelfLinkProvider来创建自链接。当我调试该类时,我意识到当为 Hibernate 代理的对象生成自链接时,它无法正常工作。

因此,我尝试DefaultSelfLinkProvider用我自己的SelfLinkProvider-interface 实现来替换它。

这可以通过以下方式完成BeanPostProcessor

  @Bean
  public BeanPostProcessor entityManagerBeanPostProcessor()
  {
    return new BeanPostProcessor()
    {
      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
      {
        return bean;
      }

      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
      {
        if (bean instanceof SelfLinkProvider)
        { return new HibernateSelfLinkProvider((SelfLinkProvider) bean); }
        return bean;
      }
    };
  }

HibernateSelfLinkProvider是一个简单的包装 a SelfLinkProvider

public class HibernateSelfLinkProvider implements SelfLinkProvider
{
  private final SelfLinkProvider selfLinkProvider;

  public HibernateSelfLinkProvider(SelfLinkProvider selfLinkProvider)
  {
    this.selfLinkProvider = selfLinkProvider;
  }

  @Override
  public Link createSelfLinkFor(Object instance)
  {
    instance = Hibernate.unproxy(instance);
    return selfLinkProvider.createSelfLinkFor(instance);
  }
}

好处Hibernate.unproxy()是它保持给定对象不变,如果它不是代理对象。

通过这个添加,我得到了正确的链接:"http://localhost:8080/admin/projects/1"。但我不确定这是否是修改行为的最佳位置。

于 2019-01-31T11:05:19.703 回答