Spring Data Rest @EmbeddedId cannot be constructed

2020-02-14 04:39发布

I have a JPA entity Person and an entity Team. Both are joined by an entity PersonToTeam. This joining entity holds a many-to-one relation to Person and one to Team. It has a multi-column key consisting of the ids of the Person and the Team, which is represented by an @EmbeddedId. To convert the embedded id back and forth to the request id I have a converter. All this follows the suggestion on Spring Data REST @Idclass not recognized

The code looks like this:

@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);
    }
}

The problem with this converter is, that the fromRequestId method gets a null as id parameter, when a post request tries to create a new personToTeam association. But there is no other information about the payload of the post. So how should an id with foreign keys to the person and the team be created then? And as a more general question: What is the right approach for dealing many-to-many associations in spring data rest?

1条回答
The star\"
2楼-- · 2020-02-14 05:37

After running into the same issue I found a solution. Your code should be fine, except I return new PersonToTeamId() instead of the DefaultIdConverter if id is null in fromRequestId().

Assuming you are using JSON in your post request you have to wrap personId and teamId in an id object:

{
  "id": {
    "personId": "foo",
    "teamId": "bar"
  },
  ...
}

And in cases where a part of the @EmbeddedId is not a simple data type but a foreign key:

{
  "id": {
    "stringId": "foo",
    "foreignKeyId": "http://localhost:8080/path/to/other/resource/1"
  },
  ...
}
查看更多
登录 后发表回答