Recursivity with Spring and Jackson

52 views Asked by At

I need to create a model with tree entities, all of then have a reference between another, I need to serializate this to my AngularJS application, using Jackson's API but, when I hit the endpoint, the JSON that is returned is wrong. There's anyway to make this? A better way or a way to fix it?

Place class:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@Entity(name = "od_places")
public class place {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String name;

    @Column
    private int number;

    @Column
    private int zone;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "place_id")
    private List<Dweller> dwellers;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "id")
    private List<Route> routes;

    @Column
    private Geometry geom;

    @Column
    private float x;

    @Column
    private float y;

    @Column
    private Date lastUpdate;

    @Column
    private Date regDate;

    @Column
    private boolean disabled;
}

Dweller class:

@Entity(name = "od_dweller")
public class Dweller {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String gender;

    @Column
    private boolean deficientient;

    @Column
    private String ageRange;

    @Column
    private String schooling;

    @Column
    private String ocupation;

    @ManyToOne
    private Place place;

    @Column
    private Date lastUpdate;

    @Column
    private Date regDate;

    @Column
    private boolean disabled;
}

Route class:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@Entity(name = "od_routes")
public class Route {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String weekDay;

    @Column
    private int trip;

    @OneToOne(orphanRemoval = true)
    private Place origin;

    @Column
    private String departureTime;

    @OneToOne(orphanRemoval = true)
    private Place destiny;

    @Column
    private String arrivalTime;

    @OneToOne(orphanRemoval = true)
    private Dweller dweller;

    @Column
    private String reason;

    @Column
    private String travelMode;

    @Column
    private Date lastUpdate;

    @Column
    private Date regDate;

    @Column
    private boolean disabled;
}

Postman response:

[
{
    "id": 1,
    "name": "Prefeito Mario de Menezes, Avenida",
    "number": 1,
    "zone": 1,
    "dwellers": [
        {
            "id": 1,
            "gender": "Masculino",
            "deficient": false,
            "ageRange": "20 Anos",
            "schooling": "Graduado",
            "ocupation": "Assalariado",
            "place": 1,
            "lastUpdate": 1583895600000,
            "regDate": 1583895600000,
            "disabled": false
        }
    ],
    "routes": [
        {
            "id": 1,
            "weekDay": "Terça-Feira",
            "trip": 1,
            "origin": 1, // THIS SHOULD BE AN OBJECT!
            "departureTime": "08:00 - 08:29",
            "destiny": {
                "id": 2,
                "logDom": "Ronat Valter Sodré, Rua",
                "numLogDom": 2,
                "ztDom": 2,
                "dwellers": [],
                "routes": [
                    {
                        "id": 2,
                        "weekDay": "Terça-Feira",
                        "trip": 2,
                        "origin": 2,
                        "departureTime": "08:30 - 08:59",
                        "destiny": 1,
                        "arrivalTime": "11:30 - 11:59",
                        "dweller": {
                            "id": 1,
                            "gender": "Masculino",
                            "deficient": false,
                            "ageRange": "20 Anos",
                            "schooling": "Graduado",
                            "ocupation": "Assalariado",
                            "place": 1, // THIS SHOULD ALSO BE AN OBJECT!
                            "lastUpdate": 1583895600000,
                            "regDate": 1583895600000,
                            "disabled": false
                        },
                        "reason": "Retorno à residência",
                        "travelMode": "Moto (como motorista)",
                        "lastUpdate": 1583895600000,
                        "regDate": 1583895600000,
                        "disabled": false
                    }
                ],
                "geom": null,
                "x": -23.274357,
                "y": -51.060287,
                "lastUpdate": 1583809200000,
                "regDate": 1583809200000,
                "disabled": false
            },
            "arrivalTime": "08:00 - 08:29",
            "dweller": {
                "id": 1,
                "gender": "Masculino",
                "deficient": false,
                "ageRange": "20 Anos",
                "schooling": "Graduado",
                "ocupation": "Assalariado",
                "place": 1,
                "lastUpdate": 1583895600000,
                "regDate": 1583895600000,
                "disabled": false
            },
            "reason": "Lazer",
            "travelMode": "Moto (como motorista)",
            "lastUpdate": 1583895600000,
            "regDate": 1583895600000,
            "disabled": false
        }
    ],
    "geom": null,
    "x": -23.266556,
    "y": -51.038334,
    "lastUpdate": 1583809200000,
    "regDate": 1583809200000,
    "disabled": false
},
2, // THIS NUMBER TWO BREAKS EVERYTHING HERE! WHERE IS MY SECOND OBJECT?
.... // The others object are returned as the first one, just the second object returns as a number 2.
]
}

A few things to make it clear: I really need the list on Place model because I want to every place I load to come with his routes. I'm working with Postgres. All the data is MOCK.

What I want: I want to solve this, make it better and learn why and how to make this works.

1

There are 1 answers

0
Alfredo Marin On BEST ANSWER

The answer that Nikolai Shevchenko gave on the comments worked for me!

"In your Place you have one-to-many relation with Route and Dweller while in Route and Dweller you have one-to-one relation (backward) with Place. So first you should properly design your tables. Also this link might be helpful with recursive Jackson references https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion"