我们正在使用spring-data-rest 2.4.2.RELEASE(使用spring-boot,JPA / Hibernate)进行项目。 我们有一个具有这种结构的数据库模型:
table A:
name: string
b -> B //meaning a reference to table B
table B:
x: number
y: number
我们需要使用REST / JSON公开实体A:
{ "name": "myName", "position": {"x": 1, "y": 3}}
我们已经有了一个适用于Position的java类:
public class Position {
@Column(nullable = true)
@JsonProperty
private Float x;
@Column(nullable = true)
@JsonProperty
private Float y;
}
因此,我们使用JPA注释创建映射到数据库表的A和B类,但是我们在A中注释了一个属性position
,其中@JsonProperty
是一个直接访问B的getter:
@RepositoryRestResource
public interface ARepository extends JpaRepository<A, Long> {
}
@Entity
public class A {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty
private Long id;
@ManyToOne( cascade = CascadeType.ALL)
@JsonIgnore
private B b;
@JsonProperty
private String name;
@JsonProperty
public Position getPosition() {
if (b == null) {
b = new B();
}
return b.getPosition();
}
@JsonProperty
public void setPosition(Position position) {
if (this.b == null) {
this.b = new B();
}
this.b.setPosition(position);
}
}
我的B对象,我不想在REST API中公开:
@Entity
public class B {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@JsonProperty
private Long id;
@Embedded
@Column(nullable = true)
private Position position;
Position getPosition() {
return position;
}
void setPosition(Position position) {
this.position = position;
}
}
使用这种结构,我可以毫无问题地将新对象发布到我的API:
curl -XPOST -H 'Accept: application/json' -H 'Content-type: application/json' localhost:12000/as -d '
{ "name": "aName", "position": {"x":1, "y":2}}'
这会创建一个对象:
{
"name" : "aName",
"position" : {
"x" : 1.0,
"y" : 2.0
},
"_links" : {
"self" : {
"href" : "http://127.0.0.1:12000/as/5"
},
"a" : {
"href" : "http://127.0.0.1:12000/as/5"
}
}
}
但是当我尝试用PUT更新对象时:
curl -XPUT -H 'Accept: application/json' -H 'Content-type: application/json' localhost:12000/as/5 -d '
{"name": "aName", "position": {"x":4, "y":3}}'
我收到此错误
{“cause”:{“cause”:{“cause”:null,“message”:null},“message”:“无法读取有效负载!;嵌套异常是java.lang.NullPointerException”},“消息“:”无法从请求中读取类型为io.epiclabs.flex.network.A的对象!;嵌套异常是org.springframework.http.converter.HttpMessageNotReadableException:无法读取有效负载!;嵌套异常是java。 lang.NullPointerException“
调试spring-data-rest代码,我发现问题出在org.springframework.data.rest.webmvc.DomainObjectReader.doMerge
第192行。
PersistentProperty<?> property = mappedProperties.getPersistentProperty(fieldName);
if (associationLinks.isLinkableAssociation(property)) {
continue;
}
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(target);
Object nested = accessor.getProperty(property);
property
为null,因为A对象中没有position
的映射信息(mappedProperties仅取自JPA映射信息)。
它似乎只是为了更新(PUT)而在POST中它只是采用POJO和Jackson映射信息来设置Position对象。
我的问题是:我们如何配置映射,以便在序列化/反序列化时,Jackson模块从JSONProperties注释中获取信息,而不是JPA实体信息?
我们可以在不改变数据库模型的情况下以不同的方式进行这种json映射吗?