Spring JPA Загруженный объект "Один ко многим" был неправильного класса - PullRequest
0 голосов
/ 08 марта 2020

У меня есть приложение Spring Boot, которое использует Spring JPA.

У меня есть следующие классы:

Negozio

@Entity
public class Negozio {
    @Id
    private String piva;

    private String nome;

    @OneToOne
    @JoinColumn
    private Posizione posizione;

    @OneToOne(mappedBy = "negozio", targetEntity = ResponsabileNegozio.class)
    private ResponsabileNegozio responsabile;

    @OneToMany(mappedBy = "negozio")
    private Set<ProdottoNegozio> prodottiEsposti;

    @OneToMany(mappedBy = "negozio")
    private Set<NegozioLocker> locker;

    @OneToMany(mappedBy = "negozio")
    private Set<RiderNegozio> rider;

    @OneToMany(mappedBy = "negozio")
    private Set<GestoreCatalogo> gestoriCatalogo;

    @OneToMany(mappedBy = "negozio", targetEntity = Cassiere.class)
    private Set<Cassiere> cassieri;

    @SuppressWarnings("unused")
    private Negozio() {

    }

    public Negozio(String piva, String nome, Posizione posizione) {
        this.piva = piva;
        this.nome = nome;
        this.posizione = posizione;
    }

    public String getNome() {
        System.out.println("getting nome");
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getPiva() {
        System.out.println("getting piva");
        return piva;
    }

    public Posizione getPosizione() {
        System.out.println("getting posizione");
        return posizione;
    }

    public String getResponsabile() {
        System.out.println("getting responsabile NEW");
        return responsabile == null ? null : responsabile.getEmail();
    }

    public Set<ProdottoNegozio> getProdottiEsposti() {
        System.out.println("getting prodotti");
        return prodottiEsposti == null ? Set.of() : this.prodottiEsposti;
    }

    public Set<Locker> getLocker() {
        System.out.println("getting locker");
        return locker == null ? Set.of() : locker.stream().map(ln -> ln.getLocker()).collect(Collectors.toSet());
    }

    public Set<RiderNegozio> getRider() {
        System.out.println("getting rider NEW");
        return rider == null ? Set.of() : rider;
    }

    public Set<Rider> getRiders() {
        System.out.println("getting rider");
        if (rider == null)
            System.out.println("NegozioRider==null");
        else {
            System.out.println("Rider size " + rider.size());
            System.out.println("To string " + rider.toString());
        }

        Set<Rider> sr = rider.stream().map(rn -> rn.getRider()).collect(Collectors.toSet());

        System.out.println("sr done ");
        System.out.println("sr size " + sr.size());
        System.out.println("sr to string " + sr.toString());

        return rider == null ? Set.of() : sr;
    }

    public void setPosizione(Posizione posizione) {
        this.posizione = posizione;
    }

    public Set<Cassiere> getCassieri() {
//here I have some problems so I tried to print some info for manual debug
        System.out.println("getting cassieri");
        if (cassieri == null)
            System.out.println("Cassieri==null");
        else {
            System.out.println("info");
            System.out.println("class " + ((Object) cassieri).getClass().getName());
//here i discover that the runtime type is PersistentSet
            PersistentSet ps = ((PersistentSet) cassieri);
            System.out.println("info2"); //this is the last printed line
            System.out.println("iterator " + ps.iterator().toString()); //this line isn't printed at all, neither the lines below;
            System.out.println("Cassieri size " + ps.size());
            cassieri.stream().findFirst().ifPresent((cassiere) -> {
                System.out.println("trovato");
                System.out.println("email " + cassiere.getEmail());
                System.out.println("nome " + cassiere.getNome());
            });
        }
        return cassieri == null ? Set.of() : cassieri;
    }

    public Set<GestoreCatalogo> getGestoriCatalogo() {
        System.out.println("getting gestoricatalogo");
        return gestoriCatalogo == null ? Set.of() : gestoriCatalogo;
    }

Cassiere

@Entity
public class Cassiere extends Persona {
    private static final long serialVersionUID = 8953780944252571288L;

    @ManyToOne
    @JoinColumn
    private Negozio negozio;

    @SuppressWarnings("unused")
    private Cassiere() {

    }

    public Cassiere(String email, String nome, String cognome, Negozio negozio) {
        super(email, nome, cognome);
        this.negozio = negozio;
        this.roles.add(Roles.CASSIERE);
    }

    public Negozio getNegozio() {
        return negozio;
    }
}

ResponsabileNegozio

@Entity
public class ResponsabileNegozio extends Persona {
    private static final long serialVersionUID = -7244028674492067048L;

    @OneToOne
    @JoinColumn
    private Negozio negozio;

    @SuppressWarnings("unused")
    private ResponsabileNegozio() {

    }

    public ResponsabileNegozio(String email, String nome, String cognome, Negozio negozio) {
        super(email, nome, cognome);
        this.negozio = negozio;
        this.roles.add(Roles.RESPONSABILE_NEGOZIO);
    }

    public ResponsabileNegozio(String email, String nome, String cognome) {
        this(email, nome, cognome, null);
    }

    public Negozio getNegozio() {
        return negozio;
    }

    public void setNegozio(Negozio negozio) {
        this.negozio = negozio;
    }
}

На самом деле я могу зарегистрировать нового Negozio через репозиторий JPA, но когда я получаю этого Negozio по его ID для возврата это в контроллере отдыха, у меня есть следующее исключение:

{
    "timestamp": "2020-03-08T16:04:45.698+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "Could not write JSON: Object [id=resemail@a.it] was not of the specified subclass [com.github.backcamino.emporio.models.GestoreCatalogo] : loaded object was of wrong class class com.github.backcamino.emporio.models.ResponsabileNegozio; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Object [id=resemail@a.it] was not of the specified subclass [com.github.backcamino.emporio.models.GestoreCatalogo] : loaded object was of wrong class class com.github.backcamino.emporio.models.ResponsabileNegozio (through reference chain: com.github.backcamino.emporio.models.Negozio[\"gestoriCatalogo\"])",
    "path": "/negozi/0123456789"
}

Очень странное поведение состоит в том, что если в классе Negozio я меняю порядок объявления Cassiere и GestoreCatalo go, сообщение об ошибке будет содержать «GestoreCatalo go» вместо «Cassiere» только потому, что я поменял порядок декларации.

В чем проблема этого кода?

...