У вас странная проблема, и вы не можете понять, как с ней справиться. Имейте простой 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, который мне нужен на стороне интерфейса для редактирования / удаления человека. Как я могу настроить весеннюю загрузку для сериализации Id?
Вот так сейчас выглядит ответ:
[{
"firstName": "Just",
"middleName": "Test",
"lastName": "Name",
"comment": "Just a comment",
"created": 1405774380410,
"updated": null,
"phoneNumbers": [{
"phoneNumber": "74575754757"
}, {
"phoneNumber": "575757547"
}, {
"phoneNumber": "57547547547"
}]
}]
UPD Есть двунаправленное отображение гибернации, возможно, это как-то связано с проблемой.
java
json
spring
spring-boot
Константин
источник
источник
@RestController
класс контроллера и удалить@ResponseBody
из методов. Также я бы посоветовал использовать классы DTO для обработки json-запросов / ответов вместо объектов домена.Ответы:
У меня недавно была такая же проблема, потому что так
spring-boot-starter-data-rest
работает по умолчанию. См. Мой вопрос SO -> При использовании Spring Data Rest после переноса приложения на Spring Boot я заметил, что свойства объекта с @Id больше не упорядочиваются в JSONЧтобы настроить его поведение, вы можете расширить доступ
RepositoryRestConfigurerAdapter
к идентификаторам для определенных классов.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); } }
источник
RepositoryRestConfigurerAdapter
вorg.springframework.data.rest.webmvc.config
The type RepositoryRestConfigurerAdapter is deprecated
. Также, похоже, не работаетRepositoryRestConfigurerAdapter
В последних версиях Indeed устарел, вам нужно реализоватьRepositoryRestConfigurer
напрямую (использоватьimplements RepositoryRestConfigurer
вместоextends RepositoryRestConfigurerAdapter
)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)); } }
Обратите внимание, что в более ранних версиях Spring Boot
2.1.0.RELEASE
вы должны расширять (теперь не рекомендуется),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 {}
источник
@SpringBootApplication
аннотацией) должен подойти.Field entityManager in com.myapp.api.config.context.security.RepositoryRestConfig required a bean of type 'javax.persistence.EntityManager' that could not be found.
@ConditionalOnBean(EntityManager.class)
inMyRepositoryRestConfigurerAdapter
, но метод не вызывается, а идентификатор все еще не отображается. Я использую данные Spring с данными Spring mybatis: github.com/hatunet/spring-data-mybatisEntityManager
является частью спецификации JPA, а MyBatis не реализует JPA (посмотрите, следует ли MyBatis за JPA? ). Итак, я думаю, вам следует настроить все сущности по очереди, используяconfig.exposeIdsFor(...)
метод, указанный в принятом ответе .Ответ от @ 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); } }
источник
С помощью Spring Boot вам нужно расширить SpringBootRepositoryRestMvcConfiguration,
если вы используете RepositoryRestMvcConfiguration, конфигурация, определенная в application.properties, может не работать
@Configuration public class MyConfiguration extends SpringBootRepositoryRestMvcConfiguration { @Override protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.exposeIdsFor(Project.class); } }
Но для временной необходимости вы можете использовать проекцию для включения идентификатора в сериализацию, например:
@Projection(name = "allparam", types = { Person.class }) public interface ProjectionPerson { Integer getIdPerson(); String getFirstName(); String getLastName();
}
источник
Класс
RepositoryRestConfigurerAdapter
устарел, начиная с версии 3.1, реализуйтеRepositoryRestConfigurer
напрямую.Шрифт: https://docs.spring.io/spring-data/rest/docs/current-SNAPSHOT/api/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurer.html.
источник
Простой способ: переименуйте вашу переменную
private Long id;
вprivate Long Id;
Работает для меня. Вы можете прочитать об этом здесь
источник
@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; } } }
источник
Хм, ладно, похоже, я нашел решение. Удаление spring-boot-starter-data-rest из файла pom и добавление @JsonManagedReference к phoneNumbers и @JsonBackReference человеку дает желаемый результат. Json в ответ больше не печатается, но теперь у него есть Id. Не знаю, что под капотом с этой зависимостью выполняет magic spring boot, но мне это не нравится :)
источник
Module
Я полагаю, что идентификатор связан с Джексоном , зарегистрированным в SDR.Просто добавьте аннотацию @JsonProperty к идентификатору, и все заработает .
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) @JsonProperty private long id;
источник