2014-06-22 12 views
6

Ho un'entità semplice con una singola raccolta mappata.Impossibile postare una raccolta

@Entity 
public class Appointment Identifiable<Integer> { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @JsonIgnore 
    private Integer id; 

    @Column(name="TRAK_NBR") 
    private String trackNumber; 

    @OneToMany(fetch =FetchType.EAGER, cascade= CascadeType.ALL) 
    @JoinColumn(name="CNSM_APT_VER_WRK_I", nullable = false) 
    private Set<Product> products = new HashSet<Product>(); 
} 

@Entity 
public class Product implements Identifiable<Integer> { 

    @Id 
    @Column(name = "CNSM_PRD_VER_WRK_I") 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @JsonIgnore 
    private Integer id; 

    @Column(name = "PRD_MDL_NBR") 
    private String model; 

    @Column(name = "PRD_SPEC_DSC") 
    private String description; 
} 

Nella mia domanda, quando ho includere solo una PagingAndSortingRepository per la nomina. Posso chiamare il comando POST con il seguente carico utile.

{ 
    "trackNumber" : "XYZ123", 
    "products": [ 
    {"model" : "MODEL", 
    "description" : "NAME" 
    }] 
} 

Quando aggiungo un PagingAndSortingRepository per il prodotto e provo la stessa POST ottengo il seguente messaggio di errore.

{ 
    "cause" : { 
    "cause" : { 
     "cause" : null, 
     "message" : null 
    }, 
    "message" : "(was java.lang.NullPointerException) (through reference chain: com..model.Appointment[\"products\"])" 
    }, 
    "message" : "Could not read JSON: (was java.lang.NullPointerException) (through reference chain: com.model.Appointment[\"products\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.model.AppointmentVerification[\"products\"])" 
} 

My GET payload with both Repositories returns this. This is my desired format. The link to products should be included 

{ 
    "trackNumber" : "XYZ123", 
    "_links" : { 
    "self" : { 
     "href" : "http://localhost:8080/consumerappointment/appointments/70" 
    }, 
    "products" : { 
     "href" : "http://localhost:8080/consumerappointment/appointments/70/products" 
    } 
} 

Con il solo repository degli appuntamenti ottengo il seguente carico utile e posso pubblicare l'elenco dei prodotti.

{ 
    "trackNumber" : "XYZ123", 
    "products" : [ { 
    "model" : "MODEL", 
    "description" : "NAME", 
    } ], 
    "_links" : { 
    "self" : { 
     "href" : "http://localhost:8080/consumerappointment/appointments/1" 
    } 
    } 
} 

risposta

4

Facciamo un passo indietro e assicurarsi che si capisce che cosa sta accadendo qui: se viene rilevato un repository, Primavera dati REST espone una dedicated set of resources per poter gestire gli aggregati gestiti dal repository tramite HTTP. Pertanto, se si dispone di repository per più entità correlate tra loro, la relazione viene rappresentata come un collegamento. Questo è il motivo per cui si vedono i prodotti in linea con solo lo AppointmentRepository in posizione e il collegamento products in posizione dopo aver creato uno ProductRepository.

Se si desidera esporre entrambi i repository come risorse, è necessario a portata di mano gli URI dei Product casi nel payload per il POST per creare un Appointment. Ciò significa che, invece di inviare questo:

{ "trackNumber" : "XYZ123", 
    "products": [ 
    { "model" : "MODEL", 
     "description" : "NAME" 
    } 
    ] 
} 

devi creare un Product prima:

POST /products 
{ "model" : "MODEL", 
    "description" : "NAME" } 

201 Created 
Location: …/products/4711 

E poi mano l'ID del prodotto al Appointment payload:

{ "trackNumber" : "XYZ123", 
    "products": [ "…/products/4711" ]} 

Nel caso in cui non si desideri nulla di tutto questo (nessuna risorsa esposta per Product in primo luogo, utilizzare @RepositoryRestResource(exported = false) su PersonRepository. d ancora ti lascia con l'istanza di bean creata per il repository, ma nessuna risorsa esportata e la risorsa esposta per Appointment s torna a inlining relativi Product s.

+0

Vedo, questo non è ovvio dal codice lassù. Naturalmente non sono nei dettagli della progettazione del database, ma una chiave esterna, non significa che debba essere impostata in primo luogo. Potrebbe essere solo il riferimento che lega il prodotto ad un appuntamento più tardi (da qui il tuo 'Set'). Detto questo, ho cercato di spiegare perché funziona come funziona. Totalmente possibile che il modello non corrisponda al tuo caso d'uso ma non puoi dover separare le radici aggregate che hanno una relazione bidirezionale tra loro per definizione. –

+0

La tabella dei prodotti ha un vincolo di chiave esterna nella tabella degli appuntamenti. Quindi creare prodotti prima non funziona. Posso superare il comportamento del POST quando ho entrambi i repository? Devo essere in grado di creare l'appuntamento e i prodotti nella stessa transazione, ma ho ancora il link ai prodotti in GET. – zachariahyoung

+0

Sì, è sufficiente fornire un controller implementato manualmente per il percorso appropriato e il metodo HTTP dovrebbe fare il trucco. Tuttavia, penso che stia mascherando un problema di progettazione fondamentale. –

Problemi correlati