如何使用 @EmbeddedId 使用 Spring Data REST 和 ConversionService?

Posted

技术标签:

【中文标题】如何使用 @EmbeddedId 使用 Spring Data REST 和 ConversionService?【英文标题】:How to use Spring Data REST and ConversionService using @EmbeddedId? 【发布时间】:2016-08-02 21:35:13 【问题描述】:

我有一个带有 Spring Data REST 的应用程序,它返回这个 JSON:


  "_embedded" : 
    "persons" : [ 
      "personDetail" : 
        "name" : "Alex",
        "surname" : "Red",
        "id" : 
          "group" : "A",
          "subclass" : "1"
        ,
        "_links" : 
          "self" : 
            "href" : "https ://localhost:8080/myApp/api/personDetails/A_1"
          
        
      
     ]
    
   

当我转到网址时:

https://localhost:8080/myApp/api/personDetails/A_1

或到这个网址:

https://localhost:8080/myApp/api/persons/04ee99a5-1578-400a-84be-d1ca87cda752/personDetail

应用返回此 JSON:


  "name" : "Alex",
  "surname" : "Red",
  "_links" : 
    "self" : 
      "href" : "https ://localhost:8080/myApp/api/personDetails/A_1"
    ,
    "personDetail" : 
      "href" : "https ://localhost:8080/myApp/api/personDetails/A_1"
    
  

“id”字段似乎消失了。哪里完结了? 如何才能获得正确的对象投影?

这是 Person 类:

@Entity
@Table
public class Person 
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    @Column(columnDefinition = "BINARY(16)", length = 16)
    private UUID id;

    @ManyToOne(fetch = FetchType.EAGER)
    private PersonDetail personDetail;

    public UUID getId() 
        return id;
    

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

    public PersonDetail getPersonDetail() 
        return personDetail;
    

    public void setPersonDetail(PersonDetail personDetail) 
        this.personDetail = personDetail;
    

这是 PersonDetail 类:

@Entity
@Table
public class PersonDetail 
    @EmbeddedId
    private PersonDetailId id;

    @Column
    private String name;

    @Column
    private String surname;

    public PersonDetailId getId() 
        return id;
    

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

    public String getName() 
        return name;
    

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

    public String getSurname() 
        return surname;
    

    public void setSurname(String surname) 
        this.surname = surname;
    

    protected String[] getExcludeFieldNames() 
        return null;
    

    @Override
    public String toString() 
        return ReflectionToStringBuilder.toStringExclude(this, getExcludeFieldNames());
    

这是 PersonDetailId 类:

public class PersonDetailId implements Serializable 

    @Column(name = "group", nullable = false)
    private String group;

    @Column(name = "subclass", nullable = false)
    private String subclass;

    public PersonDetailId() 
        super();
    

    public PersonDetailId(String group, String subclass) 
        super();
        this.group = group;
        this.subclass = subclass;
    

    public String getGroup() 
        return group;
    

    public void setGroup(String group) 
        this.group = group;
    

    public String getSubclass() 
        return subclass;
    

    public void setSubclass(String subclass) 
        this.subclass = subclass;
    

    @Override
    public String toString() 
        StringBuilder builder = new StringBuilder();
        builder.append(group).append("_").append(subclass);
        return builder.toString();
    


这是存储库 REST:

@RepositoryRestResource
public interface PersonDetailRepository extends JpaRepository<PersonDetail, PersonDetailId> 

    @RestResource(exported=false)
    PersonDetail findBySurname(String surname);


这是我使用的转换器:

@Component
public class PersonDetailIdConverter implements Converter<String, PersonDetailId> 

    @Autowired
    private PersonDetailRepository personDetailRepository;

    @Override
    public PersonDetailId convert(String source) 

        PersonDetailId result = null;

        List<PersonDetail> details = personDetailRepository.findAll();
        for (PersonDetail detail:details) 
            if (detail.getId().toString().equals(source)) 
                result = detail.getId();
                break;
            
        

        return result;
    


这是注册该转换器的配置:

@Configuration
public class CustomizedRestMvcConfiguration extends RepositoryRestConfigurerAdapter 

    @Bean
    PersonDetailIdConverter personDetailIdConverter()
        return new PersonDetailIdConverter();
    

    @Override
    public void configureConversionService(ConfigurableConversionService conversionService) 
        conversionService.addConverter(personDetailIdConverter());
        super.configureConversionService(conversionService);
    


我使用转换器是因为它是使 url 工作的唯一方法:

"href" : "https://localhost:8080/myApp/api/personDetails/A_1"

有什么想法吗? 谢谢。

编辑

这似乎取决于预测。 当我使用我创建的投影转到对象的链接时,返回的 JSON 包含我需要的所有值。

【问题讨论】:

它是spring boot,是的,所以默认情况下它不公开ID..ref:***.com/questions/24936636/… 【参考方案1】:

由于this issue 其中ResourceSupport.getId() 上有@JsonIgnore 注释,Spring Data REST 不会导出实体的 ID。但是,您可以重命名它们,例如到personId(或者只是重命名你的getter方法)。

还记得expose your IDs,正如 Alessandro C 提到的那样。

【讨论】:

【参考方案2】:

从 spring 3.1 开始,这是注册转换器的方法:

@Import(RepositoryRestMvcConfiguration.class)
public class CustomizedRestMvcConfiguration implements RepositoryRestConfigurer 

    @Override
    public void configureConversionService(ConfigurableConversionService conversionService) 
        conversionService.addConverter(new PersonDetailIdConverter());
        super.configureConversionService(conversionService);
    


【讨论】:

以上是关于如何使用 @EmbeddedId 使用 Spring Data REST 和 ConversionService?的主要内容,如果未能解决你的问题,请参考以下文章

使用 @EmbeddedId 映射时出现 Eclipse 错误

将 @EmbeddedId 与 JpaRepository 一起使用

我应该使用哪个注释:@IdClass 或 @EmbeddedId

Hibernate Envers 如何通过 EmbeddedId 的属性获取修订

使用@EmbeddedId进行映射时出现Eclipse错误

如何在 jpa 中为 EmbeddedId 编写选择命名查询?