Spring Data Rest ManytoMany POST

首先,让我解释一下我的用例。 这很直接。 有一个用户实体和一个服务实体。 我使用UserService作为连接实体(连接表)在User和Service之间有很多关联。最初,会有一些用户和一些服务集。 用户可以随时订阅任何服务。 在这种情况下,将向UserService添加一个条目。 但是,当我尝试创建一个新的UserService关联时,我得到空指针exception。 我可以单独创建用户和服务。

我的实体是:User.java

package dao.models; import java.io.Serializable; import javax.persistence.*; import com.fasterxml.jackson.annotation.JsonBackReference; @Entity @org.hibernate.annotations.Proxy(lazy=false) @Table(name="`user`", schema="emm") public class User implements Serializable { public User() { } @Column(name="id", nullable=false, unique=true) @Id @GeneratedValue(generator="EMM_USER_ID_GENERATOR") @org.hibernate.annotations.GenericGenerator(name="EMM_USER_ID_GENERATOR", strategy="native") private long id; @ManyToOne(targetEntity=dao.models.Tenant.class, fetch=FetchType.LAZY) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK}) @JoinColumns({ @JoinColumn(name="tenant_id", referencedColumnName="id", nullable=false) }) @org.hibernate.annotations.LazyToOne(value=org.hibernate.annotations.LazyToOneOption.NO_PROXY) private dao.models.Tenant tenant; @OneToOne(targetEntity=dao.models.Person.class, fetch=FetchType.LAZY) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK}) @JoinColumns({ @JoinColumn(name="Person_id", nullable=false) }) @org.hibernate.annotations.LazyToOne(value=org.hibernate.annotations.LazyToOneOption.NO_PROXY) private dao.models.Person person; @Column(name="password", nullable=true, length=255) private String password; @Column(name="email", nullable=false, length=255) private String email; @Column(name="status", nullable=true, length=255) private String status; @ManyToMany(mappedBy="user", targetEntity=dao.models.TenantGroup.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.List group = new java.util.ArrayList(); @OneToMany(mappedBy="user", targetEntity=dao.models.UserService.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.List userService = new java.util.ArrayList(); public void setId(long value) { this.id = value; } public long getId() { return id; } public void setPassword(String value) { this.password = value; } public String getPassword() { return password; } public void setEmail(String value) { this.email = value; } public String getEmail() { return email; } public void setStatus(String value) { this.status = value; } public String getStatus() { return status; } public void setTenant(dao.models.Tenant value) { this.tenant = value; } public dao.models.Tenant getTenant() { return tenant; } public void setPerson(dao.models.Person value) { this.person = value; } public dao.models.Person getPerson() { return person; } public void setGroup(java.util.List value) { this.group = value; } public java.util.List getGroup() { return group; } public java.util.List getUserService() { return userService; } public void setUserService( java.util.List userService) { this.userService = userService; } public String toString() { return String.valueOf(getId()); } } 

服务实体

 package dao.models; import java.io.Serializable; import javax.persistence.*; import com.fasterxml.jackson.annotation.JsonBackReference; @Entity @org.hibernate.annotations.Proxy(lazy=false) @Table(name="service", schema="emm") public class Service implements Serializable { public Service() { } @Column(name="service_id", nullable=false, unique=true) @Id @GeneratedValue(generator="EMM_SERVICE_SERVICE_ID_GENERATOR") @org.hibernate.annotations.GenericGenerator(name="EMM_SERVICE_SERVICE_ID_GENERATOR", strategy="native") private long id; @Column(name="service_name", nullable=false, length=255) @org.hibernate.annotations.Index(name="service_service_name") private String serviceName; @Column(name="description", nullable=true, length=255) private String description; @Column(name="app_key", nullable=false, length=255) private String appKey; @Column(name="app_token", nullable=false, length=255) private String appToken; @Column(name="learnmoreurl", length=255) private String learnMoreURL; @Column(name="trialurl", length=255) private String trialURL; @ManyToMany(mappedBy="service", targetEntity=dao.models.Device.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.List device = new java.util.ArrayList(); @OneToMany(mappedBy="service", targetEntity=dao.models.ServiceParam.class) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE}) @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.TRUE) private java.util.List serviceParams = new java.util.ArrayList(); @OneToMany(mappedBy="service", targetEntity=dao.models.TenantService.class) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.MERGE, org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.TRUE) private java.util.List tenantService = new java.util.ArrayList(); @OneToMany(mappedBy="service", targetEntity=dao.models.UserService.class) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE}) @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.TRUE) private java.util.List userService = new java.util.ArrayList(); public long getId() { return id; } public void setId(long id) { this.id = id; } public String getServiceName() { return serviceName; } public void setServiceName(String serviceName) { this.serviceName = serviceName; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getAppKey() { return appKey; } public void setAppKey(String appKey) { this.appKey = appKey; } public String getAppToken() { return appToken; } public void setAppToken(String appToken) { this.appToken = appToken; } public String getLearnMoreURL() { return learnMoreURL; } public void setLearnMoreURL(String learnMoreURL) { this.learnMoreURL = learnMoreURL; } public String getTrialURL() { return trialURL; } public void setTrialURL(String trialURL) { this.trialURL = trialURL; } public java.util.List getDevice() { return device; } public void setDevice(java.util.List device) { this.device = device; } public java.util.List getServiceParams() { return serviceParams; } public void setServiceParams( java.util.List serviceParams) { this.serviceParams = serviceParams; } public java.util.List getTenantService() { return tenantService; } public void setTenantService( java.util.List tenantService) { this.tenantService = tenantService; } public java.util.List getUserService() { return userService; } public void setUserService( java.util.List userService) { this.userService = userService; } public String toString() { return String.valueOf(getId()); } } 

最后是加入实体

UserService.java

 package dao.models; import java.io.Serializable; import javax.persistence.*; @Entity @org.hibernate.annotations.Proxy(lazy=false) @Table(name="user_service" ,schema="emm") public class UserService implements Serializable { public UserService() { } @Column(name="id", nullable=false, unique=true) @Id @GeneratedValue(generator="EMM_USER_SERVICE_ID_GENERATOR") @org.hibernate.annotations.GenericGenerator(name="EMM_USER_SERVICE_ID_GENERATOR", strategy="native") private long id; @ManyToOne(targetEntity=dao.models.User.class, fetch=FetchType.LAZY) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK}) @JoinColumns({ @JoinColumn(name="user_id", referencedColumnName="id", nullable=false) }) @org.hibernate.annotations.LazyToOne(value=org.hibernate.annotations.LazyToOneOption.NO_PROXY) private dao.models.User user; @ManyToOne(targetEntity=dao.models.Service.class, fetch=FetchType.LAZY) @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK}) @JoinColumns({ @JoinColumn(name="service_id", referencedColumnName="service_id", nullable=false) }) @org.hibernate.annotations.LazyToOne(value=org.hibernate.annotations.LazyToOneOption.NO_PROXY) private dao.models.Service service; @Column(name="param_name", nullable=false) private String paramName; @Column(name="param_value", nullable=true) private String paramValue; @OneToMany(mappedBy="userService", targetEntity=dao.models.UserServiceToken.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.List userServiceToken = new java.util.ArrayList(); public long getId() { return id; } public void setId(long id) { this.id = id; } public dao.models.User getUser() { return user; } public void setUser(dao.models.User user) { this.user = user; } public dao.models.Service getService() { return service; } public void setService(dao.models.Service service) { this.service = service; } public String getParamName() { return paramName; } public void setParamName(String paramName) { this.paramName = paramName; } public String getParamValue() { return paramValue; } public void setParamValue(String paramValue) { this.paramValue = paramValue; } public java.util.List getUserServiceToken() { return userServiceToken; } public void setUserServiceToken( java.util.List userServiceToken) { this.userServiceToken = userServiceToken; } public String toString() { return String.valueOf(getId()); } } 

现在我的问题,GET请求正常工作,但是,当我尝试创建一个新的UserService时,我得到空指针exception。

POST: http://localhost:8080/em/api/userServices/我试图将用户1与服务2请求关联:

 { "paramName": "p1", "paramValue": "v1", "service": { "href": `"http://localhost:8080/em/api/userServices/1/service/2"` }, "user": { "href": `"http://localhost:8080/em/api/userServices/1/user/1"` } } 

错误Messgae:

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

GET http://localhost:8080/em/api/userServices产生以下输出:

 { "_links" : { "self" : { "href" : "http://localhost:8080/em/api/userServices{?page,size,sort}", "templated" : true } }, "_embedded" : { "userServices" : [ { "paramName" : "p1", "paramValue" : "v1", "_links" : { "self" : { "href" : "http://localhost:8080/em/api/userServices/1" }, "userServiceToken" : { "href" : "http://localhost:8080/em/api/userServices/1/userServiceToken" }, "user" : { "href" : "http://localhost:8080/em/api/userServices/1/user" }, "service" : { "href" : "http://localhost:8080/em/api/userServices/1/service" } } }, { "paramName" : "pone", "paramValue" : "vone", "_links" : { "self" : { "href" : "http://localhost:8080/em/api/userServices/2" }, "userServiceToken" : { "href" : "http://localhost:8080/em/api/userServices/2/userServiceToken" }, "user" : { "href" : "http://localhost:8080/em/api/userServices/2/user" }, "service" : { "href" : "http://localhost:8080/em/api/userServices/2/service" } } } ] }, "page" : { "size" : 20, "totalElements" : 2, "totalPages" : 1, "number" : 0 } } 

有没有人使用Spring-data-rest成功实现了ManyToMany关联。 如果是这样,请在这方面帮助我

我想出了问题,并让它运作。

以前,我的要求是:

 { "paramName": "p1", "paramValue": "v1", "service": { "href": "http://localhost:8080/em/api/userServices/1/service/2" }, "user": { "href": "http://localhost:8080/em/api/userServices/1/user/1" } } 

我发现它应该是以下内容:

 { "paramName": "p1", "paramValue": "v1", "service": "http://localhost:8080/em/api/services/2", "user": "http://localhost:8080/em/api/users/1" } 

我觉得spring-data-rest仍然存在问题。 如果有人不这样做,请澄清一下。 即使有固定的请求,我也得到了ServiceId的空约束。 我在db中发现,服务的主键列是service_id。 即使我有正确的实体映射(服务实体中的我的Id属性正确映射到db中的service_id),它也无法工作,我不得不将列名更改为id以使其工作。

Spring-Data-Rest应该依赖于Id的实体映射吗? 如果是这样,那么仍有一个错误。

谢谢,Vivek