스프링 데이터 REST/RestRepository 아키텍처를 사용하는 간단한 개념 증명 데모가 있습니다.@OneToMany에 대한 REST를 통한 JSON 반환이 예외 (이전의 NullPointer) 예외
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Address")
public class Address implements Serializable {
public Address() {}
@Column(name="ID", nullable=false, unique=true)
@Id
@GeneratedValue(generator="CUSTOMER_ADDRESSES_ADDRESS_ID_GENERATOR")
@org.hibernate.annotations.GenericGenerator(name="CUSTOMER_ADDRESSES_ADDRESS_ID_GENERATOR", strategy="native")
private int ID;
//@RestResource(exported = false)
@ManyToOne(targetEntity=domain.location.CityStateZip.class, fetch=FetchType.LAZY)
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.PERSIST})
@JoinColumns({ @JoinColumn(name="CityStateZipID", referencedColumnName="ID", nullable=false) })
private domain.location.CityStateZip cityStateZip;
@Column(name="StreetNo", nullable=true)
private int streetNo;
@Column(name="StreetName", nullable=false, length=40)
private String streetName;
<setters and getters ommitted>
}
및 CityStateZip
에 대한 : 저장소에
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="CityStateZip")
public class CityStateZip {
public CityStateZip() {}
@Column(name="ID", nullable=false, unique=true)
@Id
@GeneratedValue(generator="CUSTOMER_ADDRESSES_CITYSTATEZIP_ID_GENERATOR")
@org.hibernate.annotations.GenericGenerator(name="CUSTOMER_ADDRESSES_CITYSTATEZIP_ID_GENERATOR", strategy="native")
private int ID;
@Column(name="ZipCode", nullable=false, length=10)
private String zipCode;
@Column(name="City", nullable=false, length=24)
private String city;
@Column(name="StateProv", nullable=false, length=2)
private String stateProv;
}
:
@RepositoryRestResource(collectionResourceRel = "addr", path = "addr")
public interface AddressRepository extends JpaRepository<Address, Integer> {
List<Address> findByStreetNoAndStreetNameStartingWithIgnoreCase(@Param("stNumber") Integer streetNo, @Param("street") String streetName);
List<Address> findByStreetNameStartingWithIgnoreCase(@Param("street") String streetName);
List<Address> findByStreetNo(@Param("streetNo") Integer strNo);
}
과 :
// @RepositoryRestResource(collectionResourceRel = "zip", path = "zip", exported = false)
@RepositoryRestResource(collectionResourceRel = "zip", path = "zip")
public interface CityStateZipRepository extends JpaRepository<CityStateZip, Integer> {
List<CityStateZip> findByZipCode(@Param("zipCode") String zipCode);
List<CityStateZip> findByStateProv(@Param("stateProv") String stateProv);
List<CityStateZip> findByCityAndStateProv(@Param("city") String city, @Param("state") String state);
}
및
의 주() 코드 나는 두 엔티티 시작@Configuration
@EnableJpaRepositories
@Import(RepositoryRestMvcConfiguration.class)
@EnableAutoConfiguration
// @EnableTransactionManagement
@PropertySource(value = { "file:/etc/domain.location/application.properties" })
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
이 코드를 사용하면 문제가 없습니다. CityStateZip을 저장하고 주소를 저장하는 동안 참조 할 수 있으며 결과 주소를 얻을 수 있습니다. 두 번째 단계는 다른 클래스를 추가하는 것이 었습니다. Address는 0에서 많은 수의 Remarks를 가질 수 있고 Remark은 하나의 Address와 묶일 수 있습니다.
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="Remark")
@SuppressWarnings({ "all", "unchecked" })
public class Remark implements Serializable {
public Remark() {
}
@Column(name="ID", nullable=false)
@Id
@GeneratedValue(generator="CUSTOMER_ADDRESSES_REMARK_ID_GENERATOR")
@org.hibernate.annotations.GenericGenerator(name="CUSTOMER_ADDRESSES_REMARK_ID_GENERATOR", strategy="native")
private int ID;
@ManyToOne(targetEntity=domain.location.Address.class, fetch=FetchType.LAZY)
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK})
@JoinColumns({ @JoinColumn(name="LocationID", referencedColumnName="ID", nullable=false) })
private domain.location.Address address_ix;
@Column(name="Comment", nullable=false, length=255)
private String comment;
<getters, setters removed>
}
및 저장소 : 그 실체는
@RepositoryRestResource(collectionResourceRel = "remarks", path = "remarks")
public interface RemarkRepository extends JpaRepository<Remark, Integer> {
}
나는이 주소에 추가 :
@OneToMany(mappedBy="address_ix", targetEntity=domain.location.Remark.class)
@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK})
@org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.TRUE)
private java.util.Set remark = new java.util.HashSet();
나는 GET .../요지 수행하여 노출 된 API를 검색 할 수 있습니다 Address 인스턴스가없는 경우. 주소 인스턴스를 데이터베이스에 저장할 수 있습니다.
"timestamp": 1418423263313,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.http.converter.HttpMessageNotWritableException",
"message": "Could not write JSON: (was java.lang.NullPointerException) (through reference chain: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"addr\"]->java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: org.springframework.hateoas.PagedResources[\"_embedded\"]->java.util.UnmodifiableMap[\"addr\"]->java.util.ArrayList[0])",
"path": "/addr"
나는 내가 @OneToMany 협회에서 뭔가 잘못을하고있는 중이 야 가정 : 나는 저장된 인스턴스가하지만 일단하는 GET을하고 .../요지, 또는 특정 인스턴스를 얻으려고, 나는 예외가 주소 또는 Remark에 @ManyToOne 또는이 두 가지를 조합하십시오. @ManyToOne, 주소에 대한 단방향 연결을 문제없이 추가했습니다. GET을 통해 주소 데이터를 가져올 수 있으려면 어떻게해야합니까? JSON은 무엇에 대해 불평하고 있습니까? (이 시점에서 데이터베이스에는 Remark 인스턴스가 없었고 @OneToMany 앞에 @JsonIgnore 주석을 추가 했는데도 여전히 오류가 발생했습니다.