gpt4 book ai didi

java - Hibernate 与 SparkJava 不兼容?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:05:58 28 4
gpt4 key购买 nike

我在延迟加载模式下将 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
}


- DAO

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 的 session 进行检查,我看到 Hibernate 正在执行查询,就好像它处于 EAGER 加载模式一样,因此它正在执行两个选择,一个用于 Supplier,一个用于 Item。

这种行为有原因吗?

谢谢!

最佳答案

我猜这里是:get("/suppliers", "application/json", supplierDao::findAll);您正在将 Supplier 对象序列化为 json。 Items 字段未标记为从序列化中排除,因此获取其值会导致 session 延迟初始化(如果 session 未关闭,则重复和第二次查询项目)。

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

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

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

  1. @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();
  2. ExclusionStrategy with custom annotation 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 中使用 items 序列化 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();

关于java - Hibernate 与 SparkJava 不兼容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55426670/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com