遇到一个奇怪的问题,不知道如何处理。有简单的POJO:
@Entity
@Table(name = "persons")
public class Person {
@Id
@GeneratedValue
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "middle_name")
private String middleName;
@Column(name = "last_name")
private String lastName;
@Column(name = "comment")
private String comment;
@Column(name = "created")
private Date created;
@Column(name = "updated")
private Date updated;
@PrePersist
protected void onCreate() {
created = new Date();
}
@PreUpdate
protected void onUpdate() {
updated = new Date();
}
@Valid
@OrderBy("id")
@OneToMany(mappedBy = "person", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
private List<PhoneNumber> phoneNumbers = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Date getCreated() {
return created;
}
public Date getUpdated() {
return updated;
}
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
public void addPhoneNumber(PhoneNumber number) {
number.setPerson(this);
phoneNumbers.add(number);
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
@Entity
@Table(name = "phone_numbers")
public class PhoneNumber {
public PhoneNumber() {}
public PhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Id
@GeneratedValue
private Long id;
@Column(name = "phone_number")
private String phoneNumber;
@ManyToOne
@JoinColumn(name = "person_id")
private Person person;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
和休息端点:
@ResponseBody
@RequestMapping(method = RequestMethod.GET)
public List<Person> listPersons() {
return personService.findAll();
}
在json响应中,除了Id之外,还有所有字段,我需要在前端编辑/删除人员。我如何配置spring引导来序列化Id呢?
这就是现在的反应:
[{
"firstName": "Just",
"middleName": "Test",
"lastName": "Name",
"comment": "Just a comment",
"created": 1405774380410,
"updated": null,
"phoneNumbers": [{
"phoneNumber": "74575754757"
}, {
"phoneNumber": "575757547"
}, {
"phoneNumber": "57547547547"
}]
}]
UPD有双向休眠映射,也许这与问题有关。
我最近有同样的问题,这是因为这是spring-boot-starter-data-rest
的默认工作方式。查看我的SO问题->在将应用程序迁移到Spring Boot后使用Spring Data Rest时,我观察到带有@Id的实体属性不再编组到JSON
要自定义它的行为,您可以扩展RepositoryRestConfigurerAdapter
以公开特定类的id。
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
@Configuration
public class RepositoryConfig extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(Person.class);
}
}
如果您需要公开所有实体的标识符:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
import javax.persistence.EntityManager;
import javax.persistence.metamodel.Type;
@Configuration
public class RestConfiguration implements RepositoryRestConfigurer {
@Autowired
private EntityManager entityManager;
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(
entityManager.getMetamodel().getEntities().stream()
.map(Type::getJavaType)
.toArray(Class[]::new));
}
}
注意,在2.1.0.RELEASE
之前的Spring Boot版本中,您必须扩展(现在已弃用) org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter
而不是直接实现RepositoryRestConfigurer
。
如果您只想公开扩展或的实体标识符实现特定的超类或接口:
...
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(
entityManager.getMetamodel().getEntities().stream()
.map(Type::getJavaType)
.filter(Identifiable.class::isAssignableFrom)
.toArray(Class[]::new));
}
如果您只想公开具有特定注释的实体的标识符:
...
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(
entityManager.getMetamodel().getEntities().stream()
.map(Type::getJavaType)
.filter(c -> c.isAnnotationPresent(ExposeId.class))
.toArray(Class[]::new));
}
样本注释:import java.lang.annotation.*;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ExposeId {}
来自@eric-peladan的回答没有开箱工作,但非常接近,也许这对以前版本的Spring Boot有效。现在它应该是这样配置的,如果我错了,请纠正我:
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter;
@Configuration
public class RepositoryConfiguration extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(User.class);
config.exposeIdsFor(Comment.class);
}
}
RepositoryRestConfigurerAdapter
类自3.1起已弃用,直接实现RepositoryRestConfigurer
。
@Configuration
public class RepositoryConfiguration implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(YouClass.class);
RepositoryRestConfigurer.super.configureRepositoryRestConfiguration(config);
}
}
字体:https://docs.spring.io/spring-data/rest/docs/current-SNAPSHOT/api/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurer.html
对于SpringBoot,您必须扩展SpringBootRepositoryRestMvcConfiguration
如果您使用RepositoryRestMvcConfiguration应用程序中定义的配置。属性可能无法工作
@Configuration
public class MyConfiguration extends SpringBootRepositoryRestMvcConfiguration {
@Override
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.exposeIdsFor(Project.class);
}
}
但是暂时需要您可以使用投影在序列化中包含id,如:
@Projection(name = "allparam", types = { Person.class })
public interface ProjectionPerson {
Integer getIdPerson();
String getFirstName();
String getLastName();
}
只需在Id中添加@JsonProperty注释,它就可以工作了。
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty
private long id;
另一种方法是在配置中实现RepositoryRestConfigurerAdapter
。(当你必须在许多地方进行封送时,这种方法将非常有用)
@Component
public class EntityExposingIdConfiguration extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
try {
Field exposeIdsFor = RepositoryRestConfiguration.class.getDeclaredField("exposeIdsFor");
exposeIdsFor.setAccessible(true);
ReflectionUtils.setField(exposeIdsFor, config, new ListAlwaysContains());
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
class ListAlwaysContains extends ArrayList {
@Override
public boolean contains(Object o) {
return true;
}
}
}
嗯,看来我找到解决办法了。从pom文件中删除spring-boot-start -data-rest,并在phoneNumbers中添加@JsonManagedReference,在person中添加@JsonBackReference,可以得到所需的输出。响应中的Json不再是打印出来的,但现在它有Id了。不知道这个依赖项下的神奇弹簧引导是什么,但我不喜欢它:)
简单方法:将变量private Long id;
重命名为private Long Id;
适合我。你可以在这里阅读更多信息
在类上实现RepositoryRestConfigurer
并使用@Configuration
注释
下面是代码片段
@Configuration
public class BasicConfig implements RepositoryRestConfigurer{
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
// TODO Auto-generated method stub
config.exposeIdsFor(Person.class);
}
}
您还可以使用静态配置方法轻松启用在几行中暴露id。
From Spring Data Rest RepsositoryRestConfigurer
docs:
static RepositoryRestConfigurer withConfig(Consumer<RepositoryRestConfiguration> consumer)
方便的方法,轻松地创建简单的RepositoryRestConfigurer实例,仅想调整RepositoryRestConfiguration。
参数:
自:consumer
-不能为空3.1
所以这适用于我在一个现有的@Configuration
注释类:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
@Configuration
public class ApplicationConfiguration {
@Bean
public RepositoryRestConfigurer repositoryRestConfigurer() {
return RepositoryRestConfigurer.withConfig(repositoryRestConfiguration ->
repositoryRestConfiguration.exposeIdsFor(Person.class)
);
}
}