with validate valid services restful restcontroller mvc implementing for advice java spring-boot integration-testing spring-data-jpa spring-data-rest

java - validate - la prueba de integración spring-data-rest falla con una simple solicitud json



spring validation controller advice (5)

Mi prueba de integración spring-data-rest falla para una simple solicitud json. Considere los siguientes modelos jpa

Order.java

public class Order { @Id @GeneratedValue// private Long id; @ManyToOne(fetch = FetchType.LAZY)// private Person creator; private String type; public Order(Person creator) { this.creator = creator; } // getters and setters }

Person.java

ic class Person { @Id @GeneratedValue private Long id; @Description("A person''s first name") // private String firstName; @Description("A person''s last name") // private String lastName; @Description("A person''s siblings") // @ManyToMany // private List<Person> siblings = new ArrayList<Person>(); @ManyToOne // private Person father; @Description("Timestamp this person object was created") // private Date created; @JsonIgnore // private int age; private int height, weight; private Gender gender; // ... getters and setters }

En mi prueba, creé a una persona mediante el uso de personRepository y orden inited por persona que pasa

Person creator = new Person(); creator.setFirstName("Joe"); creator.setLastName("Keith"); created.setCreated(new Date()); created.setAge("30"); creator = personRepository.save(creator); Order order = new Order(creator); String orderJson = new ObjectMapper().writeValueAsString(order); mockMvc.perform(post("/orders").content(orderJson).andDoPrint());

El pedido se crea pero el creador no está asociado con el pedido. También quiero pasar cuerpo de solicitud como un objeto json. En este mi objeto json debe contener creador de la siguiente manera

{ "type": "1", "creator": { "id": 1, "firstName": "Joe", "lastName": "Keith", "age": 30 } }

Si envío un cuerpo de solicitud con el siguiente json, la llamada funciona bien

{ "type": "1", "creator": "http://localhost/people/1" }

Pero no quiero enviar el segundo JSON. Alguna idea de cómo resolver el problema. Porque mi cliente ya está consumiendo la respuesta del servidor enviando el primer json. Ahora migré mi servidor para usar spring-data-rest. Después de eso, todo mi código de cliente no funciona.

¿Cómo resolver esto?


¿ cascade = CascadeType.ALL utilizar cascade = CascadeType.ALL en la anotación @ManyToOne?

public class Order { @Id @GeneratedValue// private Long id; @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)// private Person creator; private String type; public Order(Person creator) { this.creator = creator; } // getters and setters }


Creo que debes hacer dos cosas para que funcione.

  1. Maneje la deserialización apropiadamente. Como espera que Jackson @JsonCreator objeto Person anidado a través del constructor, necesita anotar esto con @JsonCreator . Mira aquí:

http://www.cowtowncoder.com/blog/archives/2011/07/entry_457.html

Una de las características más potentes de Jackson es su capacidad para usar constructores arbitrarios para crear instancias POJO, al indicar que el constructor debe usar con la anotación @JsonCreator ..................... ...................... Los creadores basados ​​en propiedades se usan generalmente para pasar uno o más parámetros obligatorios al constructor (ya sea directamente o mediante el método de fábrica). Si no se encuentra una propiedad desde JSON, se pasa null en su lugar (o, en el caso de las primitivas, el denominado valor predeterminado; 0 para las entradas, etc.).

Vea también aquí sobre por qué Jackson puede no ser capaz de resolver esto automáticamente.

https://.com/a/22013603/1356423

  1. Actualice sus asignaciones de JPA. Si la Persona asociada ahora está poblada correctamente por el deserializador Jackson, entonces al agregar las opciones de cascada JPA necesarias a la relación, entonces ambas instancias deberían persistir.

Creo que lo siguiente debería funcionar como se esperaba:

public class Order { @Id @GeneratedValue(...) private Long id; @ManyToOne(fetch = FetchType.LAZY, cascade = cascadeType.ALL) private Person creator; private String type; @JsonCreator public Order(@JsonProperty("creator") Person creator) { this.creator = creator; } }


Está asociando correctamente el orden con el creador, sin embargo, la persona no está asociada con los pedidos. Te falta el campo de List<Order> orders en la clase Person. Agregue esto, agregue anotaciones, agregue métodos para agregar orden a la persona y luego, antes de enviar JSON, debe llamar a algo como esto:

creator.addOrder(order); order.setCreator(cretr);


Hay algunas maneras de resolver su problema, pero quiero darle una pista. Solo puede guardar solo "id" de su persona y obtener la persona por "id" de su base de datos, cuando lo necesite.

Soluciona tu problema y también guarda la memoria.


Tanto las clases de Order como Person deben implementar Serializable para descomponerlas adecuadamente y reconstruirlas desde JSON .