我有一个带有pom.xml定义的休息服务:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
我也有一个Store实体:
@Data
@Entity
@FieldDefaults(level = AccessLevel.PRIVATE)
@Table(name = "magasin")
@Inheritance(strategy = InheritanceType.JOINED)
public class Store implements Serializable {
@EmbeddedId
StoreId storeId;
@Column(name = "nom")
String name;
@MapsId("businessUnitId")
@ManyToOne
@JoinColumn(name = "bu_id", referencedColumnName = "id")
BusinessUnit businessUnit;
可嵌入的商店ID:
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Embeddable
public class StoreId implements Serializable {
@Column(name = "id")
Long id;
@Column(name = "bu_id")
Long businessUnitId;
使用以下backendIdConverter:
@Component
public class StoreIdConverter implements BackendIdConverter {
@Override
public Serializable fromRequestId(String id, Class<?> entity) {
if(id != null) {
String[] param = id.split("_");
if (entity.getTypeName().equals(Store.class.getTypeName())) {
StoreId storeId = new StoreId();
storeId.setId(Long.valueOf(param[0]));
storeId.setBusinessUnitId(Long.valueOf(param[1]));
return storeId;
}
}
return id;
}
@Override
public String toRequestId(Serializable id, Class<?> entity) {
if(entity.getTypeName().equals(Store.class.getTypeName())){
StoreId storeId = (StoreId)id;
return String.format("%s_%s", storeId.getId(), storeId.getBusinessUnitId());
}
return id.toString();
}
@Override
public boolean supports(Class<?> entity) {
return true;
}
这时,我可以使用以下网址执行请求,而不会出现任何问题: http://localhost:9001/stores/1_1
资源返回:
{
"storeId" : {
"id" : 11,
"businessUnitId" : 1
},
"name" : "TEST",
"_links" : {
"self" : {
"href" : "http://localhost:9001/stores/11_1"
},
"store" : {
"href" : "http://localhost:9001/stores/11_1"
},
"businessUnit" : {
"href" : "http://localhost:9001/stores/11_1/businessUnit"
}
}
}
但是当我将与商店实体的ManyToOne关系包含到另一个这样的实体中时:
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Entity
@Table(name = "sms")
@SequenceGenerator(name = "SmsSeq", sequenceName = "sms_seq", allocationSize = 1)
@Inheritance(strategy = InheritanceType.JOINED)
public class Sms implements Serializable {
@Id
@GeneratedValue(generator = "SmsSeq", strategy = GenerationType.SEQUENCE)
@Column(name = "id", nullable = false)
Long id;
@Column(name = "message", nullable = false)
String message;
@ManyToOne(targetEntity = Store.class)
@JoinColumns({
@JoinColumn(name = "magasin_id", referencedColumnName = "id", nullable = false),
@JoinColumn(name = "bu_id", referencedColumnName = "bu_id", nullable = false)
})
Store store;
}
发布请求 http://localhost:9001/smses
{
"message": "Bonjour",
"store": "http://10.1.3.38:9001/stores/1_1"
}
抛出这种异常:
RepositoryRestExceptionHandler : JSON parse error: No converter found capable of converting from type [java.lang.String] to type [com.test.model.StoreId]; nested exception is com.fasterxml.jackson.databind.JsonMappingException: No converter found capable of converting from type [java.lang.String] to type [com.test.model.StoreId] (through reference chain: com.test.model.Sms["store"])
我了解BackendIdConverter不会解析与商店关联的url,是否可以在Request正文上实现相同的目标?