【问题标题】:Return IDs in JSON response from Spring Data REST从 Spring Data REST 返回 JSON 响应中的 ID
【发布时间】: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 spring-data-rest


【解决方案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);
          }
    
    }
    

    【讨论】:

    【解决方案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)));
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-07-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多