2014-12-13 56 views
0

我有一个简单的概念验证演示,使用Spring Data REST/RestRepository架构。我开始与两个实体:通过REST为@OneToMany返回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); 
} 

main()的代码
@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并在保存地址时参考它,并且可以获取结果地址。第二步是添加另一个类:一个地址可以有0对多的关联备注,而一个备注与一个地址关联。这实体是:

@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如果我没有任何地址实例。我仍然可以将地址实例保存到数据库。但是,一旦我有一个保存的实例,做一个GET ... /地址,或试图获得特定的情况下,我得到一个异常:

"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协会地址或备注中的@ManyToOne,或两者的组合。我已经添加了@ManyToOne,单向联系到Address并没有问题。我需要做什么才能通过GET检索地址数据? JSON在抱怨什么? (在这一点上,数据库中没有Remark实例,我甚至在@OneToMany前面添加了@JsonIgnore注释,但是我仍然得到了这个错误:

回答

0

事实证明,问题是由于auto-生成的代码。设置言论的声明缺少参数呼叫设置(或HashSet的)的类型。如果我更改代码以

@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> remark = new java.util.HashSet<Remark>(); 

代码现在工作的要求。如果不带参数时, (Spring或JSON)代码不知道如何处理该成员。