【问题标题】:Jackson and Hibernate exception with mapping杰克逊和休眠异常与映射
【发布时间】:2016-01-20 14:38:55
【问题描述】:

我在使用 Hibernate-Spring MVC 时遇到了几个问题。 这是我从控制器调用数据库实体的示例:

控制器

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

服务

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

数据库服务

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

带有命名查询的汽车服务

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

汽车仓库

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

}

汽车实体

@Entity

@Table(name = "car", catalog = "ATS") 公共类 Car 实现 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;
    }
}

车型(外键链接,一对多关系)

/**
 * 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;
    }

}

舰队实体

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

收购实体

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

我正在使用 maven 4.2.1.发布 4.3.11.决赛

当我调用我的控制器时,我收到一个异常:

com.fasterxml.jackson.databind.JsonMappingException: 没有序列化程序 找到上课 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer 并且没有 发现创建 BeanSerializer 的属性(为了避免异常, 禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS) )(通过引用 链: com.model.Response["body"]->java.util.ArrayList[0]->com.domain.Car["carType"]->com.domain.CarType_$$_jvst615_e["handler"])

我想了解是否必须从实体中删除设置变量以及如何解决映射时的此异常。谢谢 目前我在每个实体上使用 @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) ,但它是正确的吗?此外,我在实体查询中有 cicle 循环(可能是休眠工具错误地写入所有实体或我选择了错误的方式来生成实体?)

当我使用像

这样的存储库方法时
@Override
@Transactional
public List<Fleet> getFleets() {
    return fleetRepository.findAll();
}

没问题,效果很好

更新: 我在@OneToMany 变量上添加了@JsonManagedReference,在@ManyToOne 变量上添加了@JsonBackReference,它似乎可以工作,但现在在汽车中我只能看到Acquisition 而不是Fleet 和CarType(所以有JsonBackReference 的注释)而不是来自查询I接收所有对象但carType和Fleet为null,我需要相反,所以我需要fleet和carType,而不是获取 这是我找到它的链接 Infinite Recursion with Jackson JSON and Hibernate JPA issue

【问题讨论】:

  • 请参阅此线程 stackoverflow.com/questions/21708339/… 以及更多关于圈子引用 @JsonBackReference@JsonManagedReference 注释。
  • 还要确保您的实体字段具有相应的 getter/setter 对。
  • 是的 get 和 set 存在,我对休眠工具创建的一对多关系有些怀疑
  • 尝试将 @XmlRootElement 添加到您的 Car 实体,并将 @Produces({MediaType.APPLICATION_JSON}) 添加到您的 getCars
  • 你为杰克逊添加了休眠模块吗?

标签: json spring hibernate spring-mvc jackson


【解决方案1】:

尝试将 @ManyToOne(fetch = FetchType.EAGER) 添加到您的 Car 实体 - 属性 carType (或方法 getCarType - 取决于您使用的内容)。对于 EAGER fetch - Car 实体应该有实体对象而不是代理对象。

从应用程序返回实体不是一个好习惯,因为您无法控制将返回哪些关系和数据。而不是你应该返回 VO (值对象)。使用 VO 是安全的,您可以控制从应用程序返回的内容。对于从实体到 VO 对象(包括关系)的映射猪,您可以使用一些映射器,例如 Orika

【讨论】:

  • 我有点困惑,上面的实体代码是正确的吗?我不明白问题出在哪里,进入实体,进入查询,进入 mvc 等......这是我第一次使用休眠
  • 您的实体映射在哪里?在 XML 中还是在实体类中?您在 Car 和 CarType 之间有关系 - 许多汽车可以有一个 CarType - 所以您有从 Car 到 CarType 的 ManyToOne 映射。
  • 我拥有所有带有注释的配置,例如,我用一个完整的实体更新了主帖子。是的一对多关系,但如果我在两个类中都使用它,我会收到异常
  • 哪个例外?和以前一样吗?您是否尝试在 Car 中的 ManyToOne 上设置 EAGER 而不是 LAZY - 方法 getCarType?
  • 正如我所提到的 - 返回休眠实体是不好的!您应该创建 VO 对象并将休眠对象映射到 VO 对象。 ...并且在 VO 中没有循环引用
猜你喜欢
  • 1970-01-01
  • 2012-11-15
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多