我有两个实体User
和Candidat
,其中Candidat
扩展了类User
,如下所示:
用户实体:
@Entity
@Table(name="users")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="TYPE_USER",discriminatorType=DiscriminatorType.STRING,length=2)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME,include=JsonTypeInfo.As.PROPERTY,property="type")
@JsonSubTypes({
@Type(name="UC",value=Candidat.class)
})
@XmlSeeAlso({Candidat.class})
public class User implements Serializable {
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long codeUser;
//other code ...
候选实体:
@Entity
@DiscriminatorValue("UC")
@XmlType(name = "UC")
public class Candidat extends User {
private String codeMassar;
并保存一个新的Candidat,我将此存储库方法称为:
candidatRepository.save()
来自:
public interface CandidatRepository extends JpaRepository<Candidat, String> {
}
这是我的rest服务,它调用save方法:
@RequestMapping(value = "/candidats", method = RequestMethod.POST)
public Candidat saveCandidat(@RequestBody Candidat candidat) throws Exception {
return candidatMetier.saveCandidat(candidat);
}
问题是当我要保存新的Candidat时,如下所示:
{
"username": "User",
"password": "123456",
"email": "[email protected]"
}
我收到一条错误消息:
无法读取HTTP消息:
org.springframework.http.converter.HttpMessageNotReadableException:
无法读取文件:预期的凭证(END_OBJECT)
FIELD_NAME:缺少包含类型ID(用于
org.capvalue.fme.domain.Candidat类)
我从中了解到,我必须在要发送的JSON对象中指定类型,但是我认为这不是必需的,因为我保存了具有
Candidat
的新@DiscriminatorValue("UC")
,因此当其save
在User
表中,它将自动用type='UC'
保存。我该如何解决?
最佳答案
我从中了解到,我必须在json中指定类型
我发送的对象
由于已添加@JsonTypeInfo
,因此应使用type
字段指定对象实例的实际类。例如,如果将type
字段设置为UC
,Jackson将创建一个Candidat
类的实例。
但我认为没有必要,因为我保存了一个新的Candidat,
具有@DiscriminatorValue(“ UC”),因此将其保存在User表中时
它会自动以type ='UC'保存。@DiscriminatorValue
将由您的JPA提供程序处理。相反,@JsonTypeInfo
是Jackson的概念,所以不!您不能指望JPA @DiscriminatorValue
可以帮助Jackson确定对象实例的实际类型。
您应该以JSON表示形式发送type
信息,或者从@JsonTypeInfo
类中删除@JsonSubTypes
和User
。我猜想删除Jackson类型注释是更好的方法,因为您在以下位置使用了实际的子类:
public Candidat saveCandidat(@RequestBody Candidat candidat) { ... }
另外,尝试定义一些DTO并将其作为REST端点返回值返回。这种方法的一个优点是,您的Jackson和JPA元数据是分开的,因此可以避免这些问题。