从 Spring Data REST 返回 JSON 响应中的 ID

Posted

技术标签:

【中文标题】从 Spring Data REST 返回 JSON 响应中的 ID【英文标题】:Return IDs in JSON response from Spring Data REST 【发布时间】:2017-10-18 04:52:49 【问题描述】:

我有一个实体

@Entity
@Table(name = "books")
public class Book 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;

    @Column(name = "id", unique = true, nullable = false)
    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    @Column(name = "name")
    public String getName() 
        return name;
    

    public void setName(String name) 
        this.name = name;
    

我是这样初始化的

@PostConstruct
public void init() 
    List<String> newFiles = this.listFiles();
    newFiles.forEach(filename -> 
        Book book = new Book();
        book.setName(filename);

        dbRepository.save(book);
    );

如果我将save 的结果设置为Book 的实例,我可以获得id,但它不是null——所以id 被创建得很好。

我定义了一个仓库

@RepositoryRestResource
public interface IBooksRepository extends CrudRepository<Book, Long> 

我想用它来获取数据并将其设置到数据库中的books 表中。

当我尝试使用curl localhost:8080/books 访问我的repository rest 时,我得到了这个响应


   "_embedded":
      "books":[
         
            "name":"simple-file.txt",
            "_links":
               "self":
                  "href":"http://localhost:8080/books/1"
               ,
               "book":
                  "href":"http://localhost:8080/books/1"
               
            
         
      ]
   ,
   "_links":
      "self":
         "href":"http://localhost:8080/books"
      ,
      "profile":
         "href":"http://localhost:8080/profile/books"
      
   

books 元素仅返回 name。我怎样才能让它也返回id,与name处于同一级别?

【问题讨论】:

Spring boot @ResponseBody doesn't serialize entity id的可能重复 【参考方案1】:

Spring Data Rest 隐藏 ID 默认情况下,为了在 JSON 中包含它,您必须为您的实体手动配置它。根据您的 spring 版本,您可以提供自己的配置(旧):

@Configuration
public class ExposeEntityIdRestConfiguration extends RepositoryRestMvcConfiguration 

    @Override
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) 
        config.exposeIdsFor(Book.class);
    

...或注册RepositoryRestConfigurer(当前):

@Component
public class ExposeEntityIdRestMvcConfiguration extends RepositoryRestConfigurerAdapter 

  @Override
  public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) 
    config.exposeIdsFor(Book.class);
  

有关详细信息,请参阅Spring Data Rest documentation。

【讨论】:

嗯,RepositoryRestMvcConfiguration中没有方法configureRepositoryRestConfiguration 你用的是哪个版本的spring data rest? 你知道默认关闭的原因吗?看起来backbone.js需要传播id才能完全发挥作用,例如集合.get(id) 你为什么先用@Configuration,再用@Component RepositoryRestConfigurerAdapter 现已弃用,您必须直接实现 RepositoryRestConfigurer【参考方案2】:

现在有一个静态方法RepositoryRestConfigurer.withConfig 可以做与上面相同的事情。见javadoc:

轻松创建简单的 @link RepositoryRestConfigurer 实例的便捷方法,这些实例只想调整 @link RepositoryRestConfiguration。

我在their integration tests 之一中找到了用法

因此,截至目前,以下方法将是最新的:

@Bean
public RepositoryRestConfigurer repositoryRestConfigurer()

    return RepositoryRestConfigurer.withConfig(config -> 
        config.exposeIdsFor(Book.class);
    );

【讨论】:

【参考方案3】:
@Component
public class RestConfig implements RepositoryRestConfigurer 

    @Override
      public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) 
        config.exposeIdsFor(Book.class);
        //config.exposeIdsFor(Library.class);
      


【讨论】:

感谢您的贡献!您可能希望通过引用为您的答案添加描述以使其更清晰。有关指南,请参阅 ***.com/help/how-to-answer。【参考方案4】:

这是一个好方法。

@Projection(name = "customBook", types =  Book.class ) 
public interface CustomBook 
 
    @Value("#target.id")
    long getId(); 
    

信用:https://www.baeldung.com/spring-data-rest-projections-excerpts

【讨论】:

【参考方案5】:

接受的答案会覆盖已弃用的方法。这是更新版本:

@Component
public class RestConfig implements RepositoryRestConfigurer 

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) 
        config.exposeIdsFor(Book.class);
    

另一种方法是在 @SpringBootApplication 带注释的类中实现 RepositoryRestConfigurer

@SpringBootApplication
public class MyApplication implements RepositoryRestConfigurer 

    public static void main(String[] args) 
        SpringApplication.run(MyApplication.class, args);
    

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) 
        config.exposeIdsFor(Book.class);
    


【讨论】:

【参考方案6】:

这是适用于所有实体的解决方案

    @Autowired
    private EntityManager entityManager;
    
    @Bean
    public RepositoryRestConfigurer repositoryRestConfigurer() 
        return RepositoryRestConfigurer.withConfig(config -> config.exposeIdsFor(entityManager.getMetamodel().getEntities().stream().map(Type::getJavaType).toArray(Class[]::new)));
    

【讨论】:

以上是关于从 Spring Data REST 返回 JSON 响应中的 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何配置 Spring-Data-Rest 以仅返回登录用户拥有的数据

Spring Data Rest with Spring Security - 按当前用户查找所有内容

是否有适用于 JPA、spring-data、spring-data-rest 的通用 REST 查询语言

Spring Data REST 默认对 JSON 隐藏技术实体字段(@Version、@Id)。如何将它们作为通常的属性返回?

Spring Data JPA - 使用 REST 调用上的查询参数从方法名称生成查询

使用 Spring Data Rest 时如何从组件扫描中排除 @Repository