休眠与SparkJava不兼容吗?

在延迟加载模式下将Hibernate与SparkJava一起使用时出现错误.

它在没有SparkJava的情况下可以正常运行,但是在使用SparkJava时,它试图强制为OneToMany关系强制加载.

-型号

@Entity
@Table(name = "KU_SUPPLIER")
public class Supplier {

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

    @NotEmpty(message = "Please provide a name")
    private String name;

    @OneToMany(mappedBy = "supplier")
    private List<Item> items;  // Should be lazy-loaded

    // Constructor / Getters / Setters
}

-道

public class SupplierDao implements Dao<Supplier> {

    private final SessionFactory sessionFactory;

    public SupplierDao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Supplier> findAll() {
        try (Session session = sessionFactory.openSession()) {
            return session.createQuery("FROM com.seafrigousa.model.Supplier").getResultList();
        }
    }
}

-主要

// Working perfectly and lazy-load Items as desired    
supplierDao.findAll();

// The method will be called when a web browser goes to "localhost/suppliers"
// It throws org.hibernate.LazyInitializationException: Failed to lazily initialize a collection of role: model.Supplier.items,could not initialize proxy - no Session
get("/suppliers","application/json",supplierDao::findAll);

我通过不关闭DAO的会话进行检查,发现Hibernate正在执行查询,就像它处于EAGER加载模式一样,因此它正在执行两个选择,一个用于“供应商”,一个用于“项目”.

有这种现象的原因吗?

谢谢!

最佳答案
我猜这里:get(“ / suppliers”,“ application / json”,providerDao :: findAll);
您正在将Supplier对象序列化为json. Items字段未标记为从序列化中排除,因此获取其值会导致会话之外的延迟初始化(如果会话未关闭,则冗余第二项查询).

如果我的猜测是正确的,请让序列化程序忽略项目字段或在查询获取它们

session.createQuery("FROM com.seafrigousa.model.Supplier s join fetch s.items").getResultList();

使用gson作为序列化器,您有以下选择:

> @Expose注释要序列化的字段.

@Entity
@Table(name = "KU_SUPPLIER")
public class Supplier {

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

    @Expose
    @NotEmpty(message = "Please provide a name")
    private String name;

    @OneToMany(mappedBy = "supplier")
    private List<Item> items;  // Should be lazy-loaded

    // Constructor / Getters / Setters
}

随着以下gson初始化

Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();

>具有自定义注释的排除策略f.e.

public class IgnoreFieldExclusionStrategy implements ExclusionStrategy {

    @Override
    public boolean shouldSkipField(FieldAttributes fieldAttributes) {
        return fieldAttributes.getAnnotation(GsonIgnore.class) != null;
    }

    @Override
    public boolean shouldSkipClass(Class<?> aClass) {
        return false;
    }
}

带有自定义批注@GsonIgnore

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface GsonIgnore {}

和gson启动

Gson gson = new GsonBuilder().addSerializationExclusionStrategy(new IgnoreFieldExclusionStrategy()).create();

你的班级看起来像这样

@Entity
@Table(name = "KU_SUPPLIER")
public class Supplier {

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

    @NotEmpty(message = "Please provide a name")
    private String name;

    @GsonIgnore
    @OneToMany(mappedBy = "supplier")
    private List<Item> items;  // Should be lazy-loaded

    // Constructor / Getters / Setters
}

如果需要使用不同api中的项目序列化Supplier,则可以为Supplier创建DTO对象,并根据如下结果映射它:

package com.seafrigousa.dto

public class SupplierDTO {

    private int id;
    private String name;

    public SupplierDTO(int id,String name) {
        this.id = id;
        this.name = name;
   }

    // Getters / Setters
}

查询

session.createQuery("select new com.seafrigousa.dto.SupplierDTO(s.id,s.name) FROM com.seafrigousa.model.Supplier s").getResultList();

相关文章

ArrayList简介:ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增...
一、进程与线程 进程:是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位。 线程...
本文为博客园作者所写:&#160;一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 简单的一个类...
#############java面向对象详解#############1、面向对象基本概念2、类与对象3、类和对象的定义格式4、...
一、什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错。在java中,阻止当前方法或作用域...
Collection接口 Collection接口 Collection接口 Collection是最基本的集合接口,一个Collection代表一组...