我有一个JPA实体Person和一个实体Team.两者都由实体PersonToTeam连接.此加入实体与Person保持多对一关系,与Team保持一对多关系.它有一个多列密钥,由Person和Team的id组成,由@EmbeddedId表示.要将嵌入式id来回转换为请求ID,我有一个转换器.所有这些都遵循了
Spring Data REST @Idclass not recognized的建议
代码如下所示:
@Entity
public class PersonToTeam {
@EmbeddedId
@Getter
@Setter
private PersonToTeamId id = new PersonToTeamId();
@ManyToOne
@Getter
@Setter
@JoinColumn(name = "person_id", insertable=false, updatable=false)
private Person person;
@ManyToOne
@Getter
@Setter
@JoinColumn(name = "team_id", insertable=false, updatable=false)
private Team team;
@Getter
@Setter
@Enumerated(EnumType.STRING)
private RoleInTeam role;
public enum RoleInTeam {
ADMIN, MEMBER
}
}
@EqualsAndHashCode
@Embeddable
public class PersonToTeamId implements Serializable {
private static final long serialVersionUID = -8450195271351341722L;
@Getter
@Setter
@Column(name = "person_id")
private String personId;
@Getter
@Setter
@Column(name = "team_id")
private String teamId;
}
@Component
public class PersonToTeamIdConverter implements BackendIdConverter {
@Override
public boolean supports(Class<?> delimiter) {
return delimiter.equals(PersonToTeam.class);
}
@Override
public Serializable fromRequestId(String id, Class<?> entityType) {
if (id != null) {
PersonToTeamId ptid = new PersonToTeamId();
String[] idParts = id.split("-");
ptid.setPersonId(idParts[0]);
ptid.setTeamId(idParts[1]);
return ptid;
}
return BackendIdConverter.DefaultIdConverter.INSTANCE.fromRequestId(id, entityType);
}
@Override
public String toRequestId(Serializable id, Class<?> entityType) {
if (id instanceof PersonToTeamId) {
PersonToTeamId ptid = (PersonToTeamId) id;
return String.format("%s-%s", ptid.getPersonId(), ptid.getTeamId());
}
return BackendIdConverter.DefaultIdConverter.INSTANCE.toRequestId(id, entityType);
}
}
此转换器的问题是,当post请求尝试创建新的personToTeam关联时,fromRequestId方法获取null作为id参数.但是没有关于帖子有效载荷的其他信息.那么如何创建一个带有外键的id给人和团队呢?并且作为一个更普遍的问题:在Spring数据休息中处理多对多关联的正确方法是什么?
最佳答案 遇到同样的问题后,我找到了解决方案.您的代码应该没问题,除非我返回新的PersonToTeamId()而不是DefaultIdConverter,如果fromRequestId()中的id为null.
假设您在发布请求中使用JSON,则必须将personId和teamId包装在id对象中:
{
"id": {
"personId": "foo",
"teamId": "bar"
},
...
}
如果@EmbeddedId的一部分不是简单数据类型而是外键:
{
"id": {
"stringId": "foo",
"foreignKeyId": "http://localhost:8080/path/to/other/resource/1"
},
...
}