2016-01-04 5 views
8

मैं Person इकाई में एक पता सूची जोड़कर उदाहरण Accessing JPA Data with REST का विस्तार करना चाहता था।वसंत जेपीए रीस्ट वन से कई

@Entity 
public class Person { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 

    private String firstName; 
    private String lastName; 

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL) 
    private List<Address> addresses = new ArrayList<>(); 

    // get and set methods... 
} 

Address वर्ग एक बहुत ही सरल है: तो, मैं @OneToMany टिप्पणी के साथ एक सूची addresses जोड़ा

@Entity 
public class Address { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private long id; 
    private String street; 
    private String number; 
    // get and set methods... 
} 

और अंत में मैं AddressRepository इंटरफ़ेस कहा: तो फिर

public interface AddressRepository extends PagingAndSortingRepository<Address, Long> {} 

मैंने कुछ पते वाले व्यक्ति को पोस्ट करने का प्रयास किया:

curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Frodo", "lastName" : "Baggins", "addresses": [{"street": "somewhere", "number": 1},{"street": "anywhere", "number": 0}]}' http://localhost:8080/people 

त्रुटि मैं मिलता है:

Could not read document: Failed to convert from type [java.net.URI] to type [ws.model.Address] for value 'street'; 
nested exception is java.lang.IllegalArgumentException: Cannot resolve URI street. Is it local or remote? Only local URIs are resolvable. (through reference chain: ws.model.Person[\"addresses\"]->java.util.ArrayList[1]); 
nested exception is com.fasterxml.jackson.databind.JsonMappingException: Failed to convert from type [java.net.URI] to type [ws.model.Address] for value 'street'; nested exception is java.lang.IllegalArgumentException: Cannot resolve URI street. Is it local or remote? Only local URIs are resolvable. (through reference chain: ws.model.Person[\"addresses\"]->java.util.ArrayList[1]) 

उचित विधि कई रिश्ते और पोस्ट json वस्तुओं उन्हें करने के लिए कई लोगों के लिए एक और कई बनाने के लिए है कौन?

+0

आपने हमें अपने ओआरएम के लिए इकाई कक्षाएं दिखायी हैं, लेकिन आपने हमें कुछ भी नहीं दिखाया है जो आरईएसटी के लिए एनोटेटेड है। – scottb

+0

एक कस्टम कनवर्टर का उपयोग करने का सुझाव देने वाला यह जवाब देखें http://stackoverflow.com/questions/24781516/spring-data-rest-field-converter – dseibert

+1

@scottb मैं दोनों रिपॉजिटरीज़ के लिए ट्यूटोरियल में '@ रिपोजिटरी रीस्ट रिसोर्स 'एनोटेशन का उपयोग करता हूं (व्यक्ति, पता)। यह संस्थाओं के लिए सामान्य आरईएसटी अंतराल बनाता है। –

उत्तर

6

आप दो पतों पहली पोस्ट चाहिए, फिर (http://localhost:8080/addresses/1 जैसे और http://localhost:8080/addresses/2) का उपयोग अपने URL लौटे अपने व्यक्ति पोस्ट में:

curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Frodo", "lastName" : "Baggins", "addresses": ["http://localhost:8080/addresses/1","http://localhost:8080/addresses/2"]}' http://localhost:8080/people 

आप पहले व्यक्ति को बचाने के लिए चाहते हैं और फिर उसके पतों आप कर सकते थे जोड़ने ऐसा करें:

curl -i -X POST -H "Content-Type:application/json" -d '{ "firstName" : "Frodo", "lastName" : "Baggins"}' http://localhost:8080/people 
curl -i -X POST -H "Content-Type:application/json" -d '{"street": "somewhere", "number": 1}' http://localhost:8080/addresses 
curl -i -X POST -H "Content-Type:application/json" -d '{"street": "anywhere", "number": 0}' http://localhost:8080/addresses 
curl -i -X PATCH -H "Content-Type: text/uri-list" -d "http://localhost:8080/addresses/1 
http://localhost:8080/addresses/2" http://localhost:8080/people/1/addresses 
+0

यह काम करता है (यह एनोटेशन को '@ ManyToMany'' में बदलने के बदले कई रिश्तों के लिए भी काम करता है, लेकिन मुझे यह अजीब लगता है। क्या आप समझा सकते हैं कि यह इस तरह क्यों काम करता है? एक आवेदन में मैं एक व्यक्ति और फिर पते जोड़ता हूं, विपरीत नहीं। –

+0

इस दृष्टिकोण के साथ एक और बात यह है कि समर्थित HTTP विधियां 'प्राप्त करें' और 'POST' (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#_supported_http_methods) हैं। इसलिए, अगर मैं किसी मौजूदा व्यक्ति को पता जोड़ना चाहता हूं, तो मैं नहीं कर सकता। –

+0

@ एरिसएफ। मुझे लगता है कि यह संसाधनों और उनके यूआरएल (जो आपके लिए एक [हेटोएस आर्किटेक्चर] (https://en.wikipedia.org/wiki/HATEOAS)) के साथ काम करने के लिए स्प्रिंग डेटा आरईएसटी की भावना में है। व्यक्ति को पहले सहेजने का एक तरीका और उसके बाद उसे अपने पते को असाइन करना उत्तर में है (मैंने इसे अभी संपादित किया है) –

0

क्या आपकी बाकी सेवा किसी पते के बजाय किसी व्यक्ति को स्वीकार नहीं करनी चाहिए?

public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {} 

या, शायद आप दो अलग अलग बाकी सेवाओं, जो मुझे समझ नहीं आता बनाने की कोशिश कर रहे हैं। आपके पास केवल एक ही आराम सेवा होनी चाहिए जो उस व्यक्ति को ले ले, जिसमें उसमें पता प्रविष्टियां हों।

+0

आप सही हैं। मेरे पास कोड में है। मैंने इसे प्रश्न में छोड़ दिया है क्योंकि इसका उल्लेख ट्यूटोरियल में किया गया है। –

0

मैंने संदर्भित भंडार को निर्यात न करके इस समस्या को हल करने में कामयाब रहे। यह इंटरफ़ेस के शीर्ष पर एनोटेशन जोड़ रहा है। अपने उदाहरण में, यह उस तरह होगा:

@RepositoryRestResource(exported = false) 
public interface AddressRepository extends CrudRepository<Address, Long> { 
} 

यह आंशिक रूप से समस्या का समाधान स्प्रिंग डाटा के रूप में अभी भी आप के लिए विदेशी कुंजी का प्रचार नहीं करेंगे। हालांकि, यह आपके व्यक्ति और पते (उस व्यक्ति के संदर्भ के बिना) जारी रहेगा। फिर, अगर हमने इन लापता विदेशी कुंजी को अपडेट करने के लिए एपीआई को एक और कॉल किया है, तो आप एपीआई के माध्यम से अपने सभी लिंक किए गए पतों के साथ एक व्यक्ति प्राप्त कर पाएंगे - जैसे @ फ्रांसेस्को पिट्जलिस ने

मुझे आशा है कि इससे मदद मिलेगी। बस एक आखिरी नोट। मैं अभी भी इस पर काम कर रहा हूं क्योंकि मैं हास्यास्पद (साथ ही बुनियादी और आवश्यक) पर विचार करता हूं कि हाइबरनेट हमारे लिए विदेशी कुंजी का प्रचार नहीं कर सकता है। यह किसी भी तरह से संभव होना चाहिए।


संपादित: वास्तव में यह संभव था। नीचे कार्यान्वयन एक इकाई और उसके बच्चों को वसंत डेटा (आराम - जैसा कि हम भंडार का पर्दाफाश कर रहे हैं) के आधार पर आर्किटेक्चर के लिए विदेशी कुंजी का प्रचार करने में सक्षम हैं, हाइबरनेट 5.0.12 फाइनल इंजन और आईएसएसक्यूएल स्टोरेज इंजन इनो डीबी (स्मृति में नहीं) डेटाबेस)।

@Entity 
public class Producto implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
    private String nombre; 
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinColumn(name = "producto_id") 
    private List<Formato> listaFormatos; 
    //Constructor, getters and setters 
} 

https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/JoinColumn.html - यह महत्वपूर्ण था।

@Entity 
public class Formato implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Long id; 
    private Integer cantidad; 
    private String unidadMedida; 
    @ManyToOne 
    private Producto producto; 
    //Constructor, getters and setters 
} 

@RepositoryRestResource 
public interface ProductoRepository extends CrudRepository<Producto, Long> { 
} 

@RepositoryRestResource 
public interface FormatoRepository extends CrudRepository<Formato, Long> { 
} 

spring.datasource.url=jdbc:mysql://localhost:3306/(database name) 
spring.datasource.username=(username) 
spring.datasource.password=(password) 
spring.jpa.show-sql=true 

spring.jpa.hibernate.ddl-auto=create-drop 
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect 

यह बेहद महत्वपूर्ण है। आपको यह जानने की जरूरत है कि बोली को सही तरीके से सेट करने के लिए Hibernate SQL कथन चला रहा है। मेरे लिए, मेरी टेबल का स्टोरेज इंजन InnoDB है। अगला लिंक मदद की। What mysql driver do I use with spring/hibernate?

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-jpa</artifactId> 
</dependency> 
<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-rest</artifactId> 
</dependency> 
<dependency> 
    <groupId>mysql</groupId> 
    <artifactId>mysql-connector-java</artifactId> 
    <scope>runtime</scope> 
</dependency> 

केवल एक चीज है कि मैं व्याख्या करने में सक्षम नहीं किया गया है कि, अब, मैं "बच्चा" भंडार निर्यात कर सकते हैं और यह अभी भी ठीक काम करता है। कोई विचार, दोस्तों?

संबंधित मुद्दे