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

我有一个带有 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=false

logging.level.com.boeing.etl=INFO

spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

spring.jpa.generate-ddl=false

spring.jpa.show-sql=true

spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect


慕桂英546537
浏览 102回答 2
2回答

SMILET

回答之前的一件事:不要将实体作为休息服务的响应返回,因为您将服务的消费者耦合到您的数据库,因此是一种不好的做法。现在答案是:当您的控制器返回一个包含在 ResponseEntity 中的列表时。@ResponseBody 注解的意思是方法的返回值将构成 HTTP 响应的正文。由于响应中不允许有 Java 对象,因此必须将它们序列化为适合 REST 应用程序的格式,即 JSON 或 XML(这将取决于 RequestMapping 注释的生产属性的值,以及客户端接受的内容类型) .&nbsp;由于这个序列化过程,来自 EmergentTechnology 对象(由 Hibernate 管理,因此它们被代理)的 getter 方法将被调用。此调用将导致获取工件列表。因此,您要做的是将您的实体映射到服务 EmergingTechLibService (我推荐MapStruct)中的一个 VO (避免一对),避免调用工件的 getter

慕的地10843

您似乎遇到了 1+N 问题。您可以让休眠在一个查询中加载所有数据。为此,您可以将 fetch join 与您的条件一起使用。@Overridepublic List<EmergentTechnology> getAllArtifactsById(int emergentTechId) {&nbsp; &nbsp; logger.info("Enter getEmergentTechnologies");&nbsp; &nbsp; CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();&nbsp; &nbsp; CriteriaQuery<EmergentTechnology> criteriaQuery = criteriaBuilder.createQuery(EmergentTechnology.class);&nbsp; &nbsp; Root<EmergentTechnology> root = criteriaQuery.from(EmergentTechnology.class);&nbsp; &nbsp; // NEW CODE&nbsp;&nbsp; &nbsp; root.fetch("artifacts", JoinType.INNER);&nbsp; &nbsp; criteriaQuery.select(root);&nbsp; &nbsp; criteriaQuery.where(criteriaBuilder.equal(root.<Integer>get("id"), emergentTechId));&nbsp; &nbsp; List<EmergentTechnology> emergingTechnologies = entityManager.createQuery(criteriaQuery).getResultList();&nbsp; &nbsp; logger.info("Exit getEmergentTechnologies");&nbsp; &nbsp; return emergingTechnologies;}让休眠通过一个查询获取所有数据的另一种选择是使用命名实体图。虽然我不确定这是否会解决您的所有问题,但您仍然应该会看到性能提升。此外,根据您的数据的性质(在我看来,这是一组不会很大并且不会发生太大或经常变化的信息),您可以充分利用弹簧缓存,这将非常适合您的用例.另一种选择是使用休眠查询缓存。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java