2014-07-19 8 views
53

Hanno uno strano problema e non riesco a capire come affrontarlo. sono semplici POJO:Avvio a molla @ResponseBody non serializza l'ID entità

@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); 
    } 
} 

e endpoint riposo:

@ResponseBody 
@RequestMapping(method = RequestMethod.GET) 
public List<Person> listPersons() { 
    return personService.findAll(); 
} 

In risposta JSON ci sono tutti i campi tranne Id, che ho bisogno sul lato front end per modificare/eliminare persona. Come posso configurare l'avvio a molla per serializzare l'ID?

Ecco come si presenta come risposta ora:

[{ 
    "firstName": "Just", 
    "middleName": "Test", 
    "lastName": "Name", 
    "comment": "Just a comment", 
    "created": 1405774380410, 
    "updated": null, 
    "phoneNumbers": [{ 
    "phoneNumber": "74575754757" 
    }, { 
    "phoneNumber": "575757547" 
    }, { 
    "phoneNumber": "57547547547" 
    }] 
}] 

UPD Avere mapping Hibernate bidirezionale, forse è in qualche modo legato al rilascio.

+1

Avete getter e setter adeguati per il campo ID? –

+0

Sì getter e setter sono corretti – Konstantin

+0

È possibile condividere il bean completo con i metodi getter e setter –

risposta

92

Recentemente ho avuto lo stesso problema ed è perché è così che spring-boot-starter-data-rest funziona per impostazione predefinita. Vedere la mia domanda SO ->While using Spring Data Rest after migrating an app to Spring Boot, I have observed that entity properties with @Id are no longer marshalled to JSON

Per personalizzare come si comporta, è possibile estendere RepositoryRestConfigurerAdapter per esporre gli ID per classi specifiche.

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 
    protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 
     config.exposeIdsFor(Person.class); 
    } 
} 
+1

Grande, grazie! Ho cercato molto su Google ma non ho visto prima questa soluzione. – Konstantin

+1

Mi ci sono voluti un paio di giorni per trovare la risposta, grazie mille! – kapitanpattimura

+0

E non dimenticare di supportare ora getter e setter per l'id nella classe entità! .. (l'ho dimenticato e cercavo molto tempo per quello) – flipperweid

0

Hm, ok, sembra che ho trovato la soluzione. Rimuovendo spring-boot-starter-data-rest dal file pom e aggiungendo @JsonManagedReference a phoneNumbers e @JsonBackReference a person si ottiene l'output desiderato. Json in risposta non è più stampato, ma ora ha Id. Non so quale avvio magico primavera funziona sotto cappa con questa dipendenza, ma non mi piace :)

+0

È per esporre i repository Spring Data come endpoint REST. Se non vuoi quella funzione, puoi lasciarla fuori. La cosa id è da fare con un 'modulo' di Jackson che è registrato da SDR credo. –

+1

Le API RESTful non devono esporre l'ID della chiave surrogata perché non significano nulla per i sistemi esterni. Nell'architettura RESTful l'ID è l'URL canonico per quella risorsa. –

+1

Ho letto questo prima, ma onestamente non capisco come posso collegare front-end e back-end senza Id. Devo passare Id a orm per l'operazione di cancellazione/aggiornamento. Forse hai qualche link, come può essere eseguito in vero modo RESTful :) – Konstantin

4

Con Primavera Boot si devono estende SpringBootRepositoryRestMvcConfiguration
se si utilizza RepositoryRestMvcConfiguration la configurazione definire in application.properties potrebbe non lavorato

@Configuration 
public class MyConfiguration extends SpringBootRepositoryRestMvcConfiguration { 

@Override 
protected void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { 
    config.exposeIdsFor(Project.class); 
} 
} 

Ma per esigenze temporanee Puoi utilizzare la proiezione per includere id nella serializzazione come:

@Projection(name = "allparam", types = { Person.class }) 
public interface ProjectionPerson { 
Integer getIdPerson(); 
String getFirstName(); 
String getLastName(); 

}

21

risposta da @ eric-Péladan non ha funzionato out of the box, ma era abbastanza vicino, forse che ha lavorato per le versioni precedenti di Primavera di avvio. Ora, questo è come dovrebbe essere configurato, invece, mi corregga se sbaglio:

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); 
    } 
} 
+3

Confermato che questa soluzione funziona bene in Spring Boot v1.3.3.RELEASE a differenza di uno proposto da @ eric-peladan. – Polyakoff

2

Modo semplice: rinominare la variabile private Long id; a private Long Id;

funziona per me. Potete leggere di più su di esso here

+7

oh, amico ... è un tale odore di codice ... davvero, non farlo –

+0

@IgorDonin dire che alla comunità Java che ama sniffare e strisciando la semantica dai nomi di variabili/classi/funzioni ... tutto il tempo, ovunque . – EralpB

Problemi correlati