为了账号安全,请及时绑定邮箱和手机立即绑定

在控制器范围之外获取惰性集合而不调用 getter

在控制器范围之外获取惰性集合而不调用 getter

慕桂英546537 2022-06-08 17:25:40
我有一个带有 Spring JPA 的休眠实现的 Spring Boot Web 应用程序。我使用连接列注释在我的实体之间建立了一对多关系。为此,技术实体有一个成员,即 List。我已将此列表标记为延迟初始化。一切都很好,但是一旦控件移出控制器,hibernate 就会在没有调用它的情况下触发对惰性集合(List)的调用。这会导致加载网页的巨大延迟。不知道为什么休眠会在控制器范围之外触发延迟集合。我尝试过使用 Hibernate.initialize 和 Maven 字节码增强插件,但似乎没有任何效果。请帮忙实体@Entity@Table(name="EmergentTechnologies")public class EmergentTechnology implements Serializable {    private static final long serialVersionUID = 1L;    @Id    @GeneratedValue(strategy=GenerationType.AUTO)    @Column(name="ID")    private int id;    @OneToMany    @JoinColumn(name="ETID")    @Basic(fetch = FetchType.LAZY)    private List<Artifact> artifacts;@Entity@Table(name="Artifacts")public class Artifact implements Serializable {    private static final long serialVersionUID = 1L;    @Id    @GeneratedValue(strategy=GenerationType.AUTO)    @Column(name="ID")    private int id;    @Column(name="Analyst")    private String analyst;    @Column(name="ArtifactType")    private String artifactType;应用程序属性spring.mvc.favicon.enabled=falselogging.level.com.boeing.etl=INFOspring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriverspring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImplspring.jpa.generate-ddl=falsespring.jpa.show-sql=truespring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
查看完整描述

2 回答

?
SMILET

TA贡献1796条经验 获得超4个赞

回答之前的一件事:不要将实体作为休息服务的响应返回,因为您将服务的消费者耦合到您的数据库,因此是一种不好的做法。

现在答案是:当您的控制器返回一个包含在 ResponseEntity 中的列表时。@ResponseBody 注解的意思是方法的返回值将构成 HTTP 响应的正文。由于响应中不允许有 Java 对象,因此必须将它们序列化为适合 REST 应用程序的格式,即 JSON 或 XML(这将取决于 RequestMapping 注释的生产属性的值,以及客户端接受的内容类型) . 由于这个序列化过程,来自 EmergentTechnology 对象(由 Hibernate 管理,因此它们被代理)的 getter 方法将被调用。此调用将导致获取工件列表。

因此,您要做的是将您的实体映射到服务 EmergingTechLibService (我推荐MapStruct)中的一个 VO (避免一对),避免调用工件的 getter


查看完整回答
反对 回复 2022-06-08
?
慕的地10843

TA贡献1785条经验 获得超8个赞

您似乎遇到了 1+N 问题。您可以让休眠在一个查询中加载所有数据。为此,您可以将 fetch join 与您的条件一起使用。


@Override

public List<EmergentTechnology> getAllArtifactsById(int emergentTechId) {

    logger.info("Enter getEmergentTechnologies");

    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();

    CriteriaQuery<EmergentTechnology> criteriaQuery = criteriaBuilder.createQuery(EmergentTechnology.class);

    Root<EmergentTechnology> root = criteriaQuery.from(EmergentTechnology.class);


    // NEW CODE 

    root.fetch("artifacts", JoinType.INNER);


    criteriaQuery.select(root);

    criteriaQuery.where(criteriaBuilder.equal(root.<Integer>get("id"), emergentTechId));

    List<EmergentTechnology> emergingTechnologies = entityManager.createQuery(criteriaQuery).getResultList();

    logger.info("Exit getEmergentTechnologies");

    return emergingTechnologies;

}

让休眠通过一个查询获取所有数据的另一种选择是使用命名实体图。


虽然我不确定这是否会解决您的所有问题,但您仍然应该会看到性能提升。


此外,根据您的数据的性质(在我看来,这是一组不会很大并且不会发生太大或经常变化的信息),您可以充分利用弹簧缓存,这将非常适合您的用例.


另一种选择是使用休眠查询缓存。


查看完整回答
反对 回复 2022-06-08
  • 2 回答
  • 0 关注
  • 101 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信