Search code examples
hibernatejpajacksonjson-apicrnk

Relationship links in JSON to parent don't link back up one level, possibly due to two keys


I have a "Movie" class and a "Actor" class. I have mapped these in the entities as a OneToMany and vice versa (one Movie can have many Actors). Crnk is creating the endpoints and they are working nicely, apart from the link under "relationships" on the "Actor" creates a URL that is under "Actor" endpoint when it really should go back to the root Movie URL.

So under the Actors findAll relationships.movie.links.related should be:
"related": "/api/v1/movies/1"
instead of
"related": "/api/v1/actors/156/movie"
and similarly for self

Movie findAll endpoint

{
    "data": [
        {
            "id": "1",
            "type": "v1/movies",
            "attributes": {
                "name": "I.M.Movie"
            },
            "relationships": {
                "actors": {
                    "links": {
                        "self": "/api/v1/movies/1/relationships/actors",
                        "related": "/api/v1/movies/1/actors"
                    }
                }
            },
            "links": {
                "self": "/api/v1/movies/1"
            }
        }
    ],
    "meta": {
        "totalResourceCount": null
    }
}

Actor findAll endpoint

{
    "data": [
        {
            "id": "156",
            "type": "v1/actors",
            "attributes": {
                "name": "I.R.Actor"
            },
            "relationships": {
                "movie": {
                    "links": {
                        "self": "/api/v1/actors/156/relationships/movies",
                        "related": "/api/v1/actors/156/movies"
                    }
                },
            },
            "links": {
                "self": "/api/v1/actors/156"
            }
        }
    ],
    "meta": {
        "totalResourceCount": null
    }
}

Here are the entities and their relationship annotations:

MovieEntity

@Entity(name = "movie")
@JsonApiResource(type = "v1/movies")
@Data
public class MovieEntity implements BaseEntity<String> {

    @Id
    @JsonApiId
    @Column(name="MID")
    private String id;

    @JsonIgnore
    @Column(name = "ID")
    private String secondId;

    private String name;

    @OneToMany(mappedBy = "movie", cascade = CascadeType.ALL)
    @JsonApiRelation
    @JsonManagedReference
    private List<ActorEntity> actors;
}

ActorEntity

@Entity(name = "SP")
@JsonApiResource(type = "v1/actors")
@Getter
@Setter
public class ActorEntity implements BaseEntity<String> {
    @Id
    @JsonApiId
    @Column(name = "ID")
    private String id;

    private String name;

    @ManyToOne
    @JoinColumn(name = "MOVIEID", referencedColumnName = "ID")
    @JsonApiRelation(serialize = SerializeType.LAZY)
    @JsonBackReference
    private MovieEntity movie;
}

You'll notice also that Movie has two ID's, it has it's main primary key using column MID, but the column used as the foreign key is ID which is also a unique ID. This is unfortunately the set up of the database and cannot be changed. Also, as far as I can tell, using referencedColumnName should get around this issue.

If anyone has any suggestions on why this might not be working in it's current state it would be greatly appreciated
Thanks!

p.s I changed the class names for paranoia reasons, just in case I missed something and a variable somewhere doesn't quite line up


Solution

  • so far referencedColumnName annotation attribute is not supported. But it would be thinkable to introduce support for the in the JpaRelationshipRepository implementation. Currently it is strictly primary key based.