简体   繁体   English

使用Jackson注释映射休眠实体

[英]Mapping hibernate entity with Jackson annotation

I'm working with Spring, hibernate and MySql but I have some problem with seralization of query result. 我正在使用Spring,hibernate和MySql,但是我对查询结果的序列化存在一些问题。 First in my entity I added @JsonManagedReference on Set structure (@OneToMany side) and @JsonBackReference on single object reference (@ManyToOne side) and it works but I wasn't be able to retrieve all needed information (for example @ManyToOne reference). 首先在我的实体中,我在集合结构上添加了@JsonManagedReference(@OneToMany一侧),在单个对象引用上添加了@JsonBackReference(@ManyToOne一侧),它可以工作,但是我无法检索所有需要的信息(例如,@ ManyToOne引用) 。 So i swapping @JsonBackReference on set structure and @JsonManagedReference on single object but I retrieve 所以我在集合结构上交换@JsonBackReference和在单个对象上交换@JsonManagedReference但我检索

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.tablesField.TableUI["data"]->java.util.ArrayList[0]->com.domain.Car["carType"]->com.domain.CarType_$$_jvst744_f["handler"])

I tried also with @JsonIgnore on Set structure but it doesn't work for the same issues. 我也在Set结构上尝试了@JsonIgnore,但是对于相同的问题它不起作用。 This is my spring configuration 这是我的弹簧配置

private Properties getHibernateProperties() {
        Properties properties = new Properties();
        properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
//      properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
        properties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));
        properties.put("hibernate.enable_lazy_load_no_trans",true);
        return properties;

and this is part of one of my several entities: 这是我几个实体之一的一部分:

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

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private Integer idCar;
        @JsonManagedReference
        private CarType carType;
        @JsonManagedReference
        private Fleet fleet;
        private String id;
        private int initialKm;
        private String carChassis;
        private String note;
        @JsonBackReference
        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;
        }

    }

one method that uses the query: 一种使用查询的方法:

@Override
    @RequestMapping(value = { "/cars/{idFleet}"}, method = RequestMethod.GET)
    public @ResponseBody TableUI getCars(@PathVariable int idFleet) {   
        TableUI ajaxCall=new TableUI();
        try {   
            ajaxCall.setData(fleetAndCarService.findCarsByIdFleet(idFleet));
            return ajaxCall;
        } catch (QueryException e) {
            ErrorResponse errorResponse= ErrorResponseBuilder.buildErrorResponse(e);
            LOG.error("Threw exception in FleetAndCarControllerImpl::addCar :" + errorResponse.getStacktrace());
            return ajaxCall;
        }
    }

two class for the query: 两类查询:

public interface DefRdiRepository extends JpaRepository<DefRdi, Integer>{


    //@Query("SELECT CASE WHEN COUNT(c) > 0 THEN true ELSE false END FROM DefRdi c WHERE c.parName = ?1 AND c.description= ?2")
    //Boolean existsByParNameAndDescription(String parName, String description);
    //Query method of spring, I put findBy and then the key of research 
    DefRdi findByParNameAndDescription(String parName, String description);
}

public interface CarRepository extends JpaRepository<Car, Integer>, CarRepositoryCustom {

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

}

Where is my error? 我的错误在哪里? I don't want Set object but only the single reference. 我不想要Set对象,而只想要单个引用。 The problem is only when I serialize. 问题只有当我序列化时。 Thanks 谢谢

UPDATE : I use @JSonIgnore on all set collectionts and Eager instead lazy ad all works fine, but is there a way to retrieve all the information only when I want, for example having two different query? 更新 :我在所有集合collectionts上使用@JSonIgnore,而Eager代替了惰性广告都可以正常工作,但是有一种方法只能在需要时才检索所有信息,例如有两个不同的查询吗? So it doesn't work 所以它不起作用

@Override
@Transactional
public List<Car> findByFleetIdFleet(int idFleet) {
    List<Car> carList= carRepository.findByFleetIdFleet(idFleet);
    for (Car car:carList){
        Hibernate.initialize(car.getCarType());
        Hibernate.initialize(car.getFleet());
    }
    return carList; 
    //      return carRepository.findByFleetIdFleet(idFleet);
}

All collections need to be fetched eagerly when loading them from data base, in order to get serialized by Spring. 从数据库加载它们时,需要急切地获取所有集合,以便由Spring进行序列化。 Make sure you fetch them eagerly (eg FetchMode.JOIN). 确保您热切地获取它们(例如FetchMode.JOIN)。 You could also swap @JsonManagedReference from wanted fields with @JsonIgnore to black listed fields, Spring automatically serialises every field without annotation. 您也可以将@JsonIgnore的@JsonManagedReference从需要的字段交换为黑色列出的字段,Spring会自动序列化每个没有注释的字段。

Update : 更新

Changing the data repository to something like that should work, I am not sure it compiles, but I think you will get the point: 将数据存储库更改为类似的内容应该可以,但我不确定它是否可以编译,但是我想您会明白的:

@EntityGraph(value = "some.entity.graph", type = EntityGraph.EntityGraphType.FETCH)
@Query(
        value = "SELECT c FROM Car c INNER JOIN FETCH c.acquisitions WHERE c.id = :idFleet"
)
public interface CarRepository extends JpaRepository<Car, Integer>, CarRepositoryCustom {

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

}

For more information look at this post and read the official documentation . 有关更多信息,请参见这篇文章并阅读官方文档

Workaround: 解决方法:

There seems to be a workaround , however fetching those collections eager like shown above should have a positive performance impact, since there is no need for loading proxies afterwards. 似乎有一种解决方法 ,但是获取上面渴望显示的那些集合应该会对性能产生积极的影响,因为此后无需加载代理。 Also no open transactions are needed at controller level. 同样,在控制器级别也不需要公开交易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM