0

I have several problems with Hibernate-Spring MVC. This is an example of my call from controller to database entity:

controller

@Override
    @RequestMapping(value = { "/cars/{idFleet}"}, method = RequestMethod.GET)
    public @ResponseBody Response<List<Car>> getCars(@PathVariable int idFleet) throws QueryException{  
        return fleetAndCarService.findCarsByIdFleet(idFleet);
    }

services

    @Override
//  @Transactional
    public Response<List<Car>> findCarsByIdFleet(int idFleet) throws QueryException {
        try{
            return new Response<List<Car>>(HttpStatus.OK.value(),databaseFleetsAndCarsServices.findCarsByIdFleet(idFleet));
        } catch (Exception e) {
            throw new QueryException(e);
        }
    }

database services

@Override
    public List<Car> findCarsByIdFleet(int idFleet) {
        return carServices.findByFleetIdFleet(idFleet);
    }

car services with named query

@Override
@Transactional
public List<Car> findByFleetIdFleet(int idFleet) {
    return carRepository.findByFleetIdFleet(idFleet);
}

car repository

public interface CarRepository extends JpaRepository<Car, Integer> {

    //Query method of spring, I put findBy and then the key of research 
    List<Car> findByFleetIdFleet(int idFleet);

}

car entity

@Entity

@Table(name = "car", catalog = "ATS") public class Car implements java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
private Integer idCar;
private CarType carType;
private Fleet fleet;
private String id;
private int initialKm;
private String carChassis;
private String note;
private Set<Acquisition> acquisitions = new HashSet<Acquisition>(0);

public Car() {
}

public Car(CarType carType, Fleet fleet, int initialKm, String carChassis) {
    this.carType = carType;
    this.fleet = fleet;
    this.initialKm = initialKm;
    this.carChassis = carChassis;
}

public Car(CarType carType, Fleet fleet, String id, int initialKm, String carChassis, String note,
        Set<Acquisition> acquisitions) {
    this.carType = carType;
    this.fleet = fleet;
    this.id = id;
    this.initialKm = initialKm;
    this.carChassis = carChassis;
    this.note = note;
    this.acquisitions = acquisitions;
}

@Id
@GeneratedValue(strategy = IDENTITY)

@Column(name = "id_car", unique = true, nullable = false)
public Integer getIdCar() {
    return this.idCar;
}

public void setIdCar(Integer idCar) {
    this.idCar = idCar;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_carType", nullable = false)
public CarType getCarType() {
    return this.carType;
}

public void setCarType(CarType carType) {
    this.carType = carType;
}

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id_fleet", nullable = false)
public Fleet getFleet() {
    return this.fleet;
}

public void setFleet(Fleet fleet) {
    this.fleet = fleet;
}

@Column(name = "id", length = 5)
public String getId() {
    return this.id;
}

public void setId(String id) {
    this.id = id;
}

@Column(name = "initialKm", nullable = false)
public int getInitialKm() {
    return this.initialKm;
}

public void setInitialKm(int initialKm) {
    this.initialKm = initialKm;
}

@Column(name = "carChassis", nullable = false, length = 20)
public String getCarChassis() {
    return this.carChassis;
}

public void setCarChassis(String carChassis) {
    this.carChassis = carChassis;
}

@Column(name = "note", length = 100)
public String getNote() {
    return this.note;
}

public void setNote(String note) {
    this.note = note;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "car")
public Set<Acquisition> getAcquisitions() {
    return this.acquisitions;
}

public void setAcquisitions(Set<Acquisition> acquisitions) {
    this.acquisitions = acquisitions;
    }
}

car type (linked by foreign key ,one to many relationship)

/**
 * CarType generated by hbm2java
 */
@Entity
@Table(name = "carType", catalog = "ATS")
public class CarType implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private String idCarType;
    private String note;
    private Set<Car> cars = new HashSet<Car>(0);

    public CarType() {
    }

    public CarType(String idCarType) {
        this.idCarType = idCarType;
    }

    public CarType(String idCarType, String note, Set<Car> cars) {
        this.idCarType = idCarType;
        this.note = note;
        this.cars = cars;
    }

    @Id

    @Column(name = "id_carType", unique = true, nullable = false, length = 5)
    public String getIdCarType() {
        return this.idCarType;
    }

    public void setIdCarType(String idCarType) {
        this.idCarType = idCarType;
    }

    @Column(name = "note", length = 100)
    public String getNote() {
        return this.note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "carType")
    public Set<Car> getCars() {
        return this.cars;
    }

    public void setCars(Set<Car> cars) {
        this.cars = cars;
    }

}

fleet entity

@Entity
@Table(name = "fleet", catalog = "ATS")
public class Fleet implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer idFleet;
    private Ecu ecu;
    private String application;
    private String cubic;
    private int power;
    private String euroClass;
    private String engineType;
    private String traction;
    private String transmission;
    private String note;
    private Set<Car> cars = new HashSet<Car>(0);

Acquisition entity

@Entity
@Table(name = "acquisition", catalog = "ATS")
public class Acquisition implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private Integer idAcquisition;
    private Car car;
    private DpfWeighting dpfWeighting;
    private MissionProfile missionProfile;
    private OilSample oilSample;
    private Shift shift;
    private SwVersion swVersion;
    private Date date;
    private float sessionDuration;
    private int beginKm;
    private int endKm;
    private String driverName;
    private String dataset;
    private String drChannelsConf;
    private String excelRow;
    private Set<Rdi> rdis = new HashSet<Rdi>(0);
    private Set<SelfLearning> selfLearnings = new HashSet<SelfLearning>(0);
    private Set<Iupr> iuprs = new HashSet<Iupr>(0);

I'm using maven with 4.2.1.RELEASE 4.3.11.Final

When I call my controller I receive one exception:

com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.model.Response["body"]->java.util.ArrayList[0]->com.domain.Car["carType"]->com.domain.CarType_$$_jvst615_e["handler"])

I would like to understand if I have to remove set variable from entity and how can I resolve this exception on mapping. Thanks For the moment I'm using @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) on each entity, but it is correct?Futhermore I have cicle loop into entity query (is it possible that hibernate tool wrong with write all entity or that I have seleceted the wrong way to generate entity?)

When I use repository methods like

@Override
@Transactional
public List<Fleet> getFleets() {
    return fleetRepository.findAll();
}

no problem, it works very well

UPDATE: I added @JsonManagedReference on @OneToMany variable and @JsonBackReference on @ManyToOne variable and it seems to work but now in car I can see only Acquisition and not Fleet and CarType (so there was annotation with JsonBackReference) instead from query I receive all the object but carType and Fleet are null, I need the opposite, so I need fleet and carType, not acquisition This is the link where I found it Infinite Recursion with Jackson JSON and Hibernate JPA issue

Community
  • 1
  • 1
luca
  • 3,248
  • 10
  • 66
  • 145
  • see this thread http://stackoverflow.com/questions/21708339/avoid-jackson-serialization-on-non-fetched-lazy-objects and more specially for circle references `@JsonBackReference` and `@JsonManagedReference` annotations. – Nikolay Rusev Oct 21 '15 at 14:37
  • also be sure that you have corresponding getters/ setters pair for your entity fields. – Nikolay Rusev Oct 21 '15 at 14:39
  • yes get and set are present, I have some doubt about the one to many relationship created by hibernate tool – luca Oct 21 '15 at 14:42
  • Try to add `@XmlRootElement` to your Car entity and `@Produces({MediaType.APPLICATION_JSON})` to your `getCars` – Maraboc Oct 21 '15 at 14:43
  • did you add hibernate module for jackson? – Nikolay Rusev Oct 22 '15 at 07:30
  • no, I have tried just now with com.fasterxml jackson-module-hibernate 1.9.1 but obtain ever Infinite recursion (StackOverflowError) – luca Oct 22 '15 at 07:36
  • what kind of infinite recursion? be more specific and you should register jackson hibernate module in your app. Did you saw the first link that I sent? – Nikolay Rusev Oct 22 '15 at 08:18
  • yes, but I am confused between the various suggestions. I resolved recursion as specified in the main post update, but in my json object (car) I can see only acquisition an not fleet and typeCar(annotated with @JsonBackReference) – luca Oct 22 '15 at 08:24

1 Answers1

0

Try add @ManyToOne(fetch = FetchType.EAGER) to your Car entity - attribute carType (or method getCarType - depends on what you use). For EAGER fetch - Car entity should have entity object instead of proxy object.

It is not good practice to return entities from application, because you can't control what relations and data would be returned. Instead of you should return VO (value objects). Using VO is safe and you have control what you return from application. For mappigs from entites to VO object (including relations) you can use some mapper, Orika for example.

  • I'm little confused, the code above of entity is correct? I don't understand where is the problem, into entity, into query, into mvc etc... this is my first time with hibernate – luca Oct 21 '15 at 15:31
  • Where is yours entity mappings? In XML or in entity classess? You have relation between Car and CarType - many cars can have one CarType - so you have ManyToOne mapping from Car to CarType. – Pavel Stánek Oct 21 '15 at 16:52
  • I have all the configurations with annotation, I updated main post with one entire entity for example. Yes one to many relationship but if I use this in both the classes I receive exception – luca Oct 22 '15 at 06:53
  • Which exception? The same as before? Did you try set EAGER instead of LAZY on ManyToOne in Car - method getCarType? – Pavel Stánek Oct 22 '15 at 08:13
  • And as I mentioned - it is not good to return hibernate entities! You should create VO objects and map hibernate object to VO object. ...and without circular references in VOs – Pavel Stánek Oct 22 '15 at 08:16
  • I resolved with annotation '@JsonManagedReference' and '@JsonBackReference', but now in car I can see only Acquisition and not Fleet and CarType (so there was annotation with JsonBackReference). is there an example page with mapping entity-Vo? – luca Oct 22 '15 at 08:26
  • VO or POJO - You create new classes, for example CarVO, FleetVO, etc. These classes can be same as hibernate objects, CarVO contains CarTypeVO, FleetVO has CarVO list etc. Advantage of this solution is that you know what is exactly returned from controller and You can have different outputs. You can have for example CarListVO for list of cars with precomputed values etc. For automatic mapping (including relations) from hibernate objects to VO objects you can use Orika mapper, in [this](http://orika-mapper.github.io/orika-docs/mappings-via-classmapbuilder.html) page is simple mappings. – Pavel Stánek Oct 24 '15 at 19:30