2014-06-26 6 views
11

Ich versuche eine einfache Spring-App zu erstellen. Es muss REST-Endpunkte verfügbar machen und in einer relationalen Datenbank speichern.Spring Data REST - Mehrere Assoziationslinks mit demselben Beziehungstyp gefunden

Ich nahm Ihr Beispielprojekt, http://spring.io/guides/gs/accessing-data-rest/. Ich kann alle Operationen (POST, PATCH, PUT, GET) ausführen, wie in Ihrem Handbuch erwähnt.

Allerdings habe ich versucht, Hinzufügen von Beziehungen zu Person Entity-Klasse und Dinge beginnen auseinander zu fallen.

@Entity 
public class Person { 

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

    private String firstName; 
    private String lastName; 

    @OneToOne(cascade = {CascadeType.ALL}) 
    private PersonDetails personDetails; 

    @OneToOne(cascade = {CascadeType.ALL}) 
    private PersonChildren personChildren; 

    ///Getter and setters for everything except id. 
} 


@Entity 
public class PersonChildren { 

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

    private String childFirstName; 
    private String childLastName; 

    @OneToOne(mappedBy="personChildren", optional=false) 
    private Person person; 

///Getter and setters for everything except id. 
} 


@Entity 
public class PersonDetails { 

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

    private String email; 
    private String phoneNumber; 

    @OneToOne(mappedBy="personDetails",optional=false) 
    private Person person; 

///Getter and setters for everything except id. 
} 


@RepositoryRestResource(collectionResourceRel = "people", path = "people") 
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> { 

    List<Person> findByLastName(@Param("name") String name); 

} 

build.gradle

buildscript { 
    repositories { 
     maven { url "http://repo.spring.io/libs-release" } 
     mavenLocal() 
     mavenCentral() 
    } 
    dependencies { 
     classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.1.RELEASE") 
    } 
} 

apply plugin: 'java' 
apply plugin: 'eclipse' 
apply plugin: 'idea' 
apply plugin: 'spring-boot' 

jar { 
    baseName = 'gs-accessing-data-rest' 
    version = '0.1.0' 
} 

repositories { 
    mavenLocal() 
    mavenCentral() 
    maven { url "http://repo.spring.io/libs-release" } 
} 

dependencies { 
    compile("org.springframework.boot:spring-boot-starter-web") 
    compile("org.springframework.boot:spring-boot-starter-data-jpa") 
    compile("com.h2database:h2") 
    compile("org.springframework.data:spring-data-rest-webmvc") 
} 

task wrapper(type: Wrapper) { 
    gradleVersion = '1.11' 
} 

Call:

$ curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName":"John", "lastName": "Doe", "personDetails": { "email": "[email protected]", "phoneNumber": "001-002-0003" }, "personChildren": {"childFirstName": "Mary", "childLastName": "Martin" } }' <code> http://localhost:8080/people </code> 

Response: 
HTTP/1.1 201 Created 
Server: Apache-Coyote/1.1 
<code> 
Location: http://localhost:8080/people/1 
</code> 
Content-Length: 0 
Date: Thu, 26 Jun 2014 05:42:45 GMT 

$ curl http://localhost:8080/people 

{ 
    "timestamp" : 1403761371011, 
    "status" : 500, 
    "error" : "Internal Server Error", 
    "exception" : "org.springframework.http.converter.HttpMessageNotWritableException", 
    "message" : "Could not write JSON: Detected multiple association links with same relation type! Disambiguate association @javax.persistence.OneToOne(optional=false, targetEntity=void, cascade=[], fetch=EAGER, orphanRemoval=false, mappedBy=personChildren) private com.ds.dao.rest.Person com.ds.dao.rest.PersonChildren.person using @RestResource! (through reference chain: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"people\"]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Detected multiple association links with same relation type! Disambiguate association @javax.persistence.OneToOne(optional=false, targetEntity=void, cascade=[], fetch=EAGER, orphanRemoval=false, mappedBy=personChildren) private com.ds.dao.rest.Person com.ds.dao.rest.PersonChildren.person using @RestResource! (through reference chain: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"people\"]->java.util.ArrayList[0])", 
    "path" : "/people" 
} 

Frage 1: Ich bin in der Lage andernfalls einen Beitrag aber meine GET hält zu tun.

Frage 2: Warum bekomme ich diesen Fehler, wenn Post erfolgreich ist?

Frage 3: Gibt es einen guten Spring Guide, der bei REST und JPA hilft? Wenn Sie noch an diesen Modulen arbeiten, welche Beispiele kann ich mir ansehen?

Frage 4: Ist @RepositoryRestResource das Problem? Es wird nicht erkannt, wenn ich spring-data-rest-webmvc als Abhängigkeit hinzufüge.

Dies ist auf die offene Frage ist ähnlich Spring Data Rest Ambiguous Association Exception

aktualisieren:

Es mit nur einem OneToOne Mapping in Person Klasse arbeitet. Wenn ich beide Klassen, und personChildren in Person mit OneToOne Mapping hinzufügen. Es funktioniert nicht.

Ich habe auch versucht, @JointColumn(name="person_details") und @JointColumn(name="person_children") zu personDetails und personChildren hinzuzufügen. Es hat auch nicht funktioniert.

Antwort

14

Der Grund dafür ist ziemlich einfach: Die Beziehungsnamen für assoziierte Entitäten werden von den Eigenschaftsnamen der enthaltenden Klasse abgeleitet. Also beide PersonDetails und PersonChildren möchten eine ausgehende Verbindung zu einem Person namens person erstellen. Wenn wir das gemacht, wäre es so etwas wie dies

{ _links : { 
    person : { href : … }, <- the one from PersonDetails 
    person : { href : … } <- the one from PersonChildren 
} 

aussieht Diese ungültigen Kurs. Außerdem würde die beiden Verbindungen in einem Array Schlange nicht zulassen, dass Sie zwischen den beiden Links unterscheiden mehr (die man herkommt PersonDetails und welche herkommt PersonChildren

So gibt es ein paar Möglichkeiten:.

  1. Namen manuell die Beziehungen dieser Typen. Sie können die Person Eigenschaften mit @RestResource mit Anmerkungen versehen können und konfigurieren Sie das rel Attribut der Anmerkung zu etwas anderes als person.
  2. Sie möchten eines der beiden überhaupt nicht exportiert. Die gleiche Annotation kann verwendet werden, um zu verhindern, dass die Verbindung überhaupt gerendert wird. Setzen Sie einfach das exported Flag in @RestResource auf false und der Link wird nicht gerendert. Dies könnte nützlich sein, wenn der Zeiger z.B. von PersonDetails ist nur relevant innerhalb des Codes, aber eigentlich nicht in einer JSON-Darstellung.
+0

Oliver, das hat wie ein Charme funktioniert. Ich habe die Option 1 benutzt. Danke für deine Hilfe. – user827096

+3

Ich habe beide Optionen ausprobiert, keiner arbeitet von mir. –

Verwandte Themen