休眠惰性加载使得标准运行缓慢 [英] Hibernate Lazy Loading makes criteria slow to run

查看:113
本文介绍了休眠惰性加载使得标准运行缓慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了hibernate和延迟加载对象的问题。
基本上我想加载一个有急切加载字段的类,并且不加载子类的惰性字段。

取下面的QuestionVO类

  @Entity 
@Table(name =question)
public class QuestionVO extends BaseDAOVO implements Serializable {

/ **
*
* /
private static final long serialVersionUID = -5867047752936216092L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name =id,unique = true,nullable = false)
private Integer ID;

@Column(name =questionText,unique = false,nullable = false,length = 4000)
@Size(min = 3,max = 4000)
@Pattern (regexp = MobileAppsRegexConstants.GENERAL_ALLOWED_CHARCHTERS,message =Question Text Not valid。)
private String questionText;

@ManyToOne(fetch = FetchType.EAGER)
@Cascade({CascadeType.SAVE_UPDATE})
@JoinColumn(name =MENU_STYLE_ID,nullable = true)
私人MenuStyleVO menuStyle;


以下是MenuStyleVO类

  @Entity 
@Table(name =menu_style)
public class MenuStyleVO extends BaseDAOVO implements Serializable {

/ **
*
* /
private static final long serialVersionUID = 3697798179195096156L;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name =id,unique = true,nullable = false)
private Integer ID;

@Column(name =menuStyleName,unique = false,nullable = false,length = 200)
private String menuStyleName;

@Column(name =menuTemplate,unique = false,nullable = false,length = 200)
private String menuTemplate;

@OneToOne(fetch = FetchType.LAZY,可选= false)
@Cascade({CascadeType.SAVE_UPDATE})
@JoinColumn(name =logo_id)
@JsonProperty(徽标)
私人ApplicationImageVO徽标;


}



和这个ApplicationImageVO类



$ $ p $ $ $ $ c $ @Entity
@Table(name =application_image)
public class ApplicationImageVO extends BaseDAOVO implements Serializable {

/ **
*
* /
private static final long serialVersionUID = -9158898930601867545L;

@OneToOne(fetch = FetchType.LAZY,mappedBy =image1242x2208)
@Cascade({CascadeType.ALL})
@JsonIgnore
private SubmissionLauncherImagesVO launcherImage1242x2208;

@OneToOne(fetch = FetchType.LAZY,mappedBy =image1536x2048)
@Cascade({CascadeType.ALL})
@JsonIgnore
private SubmissionLauncherImagesVO launcherImage1536x2048;

@OneToOne(fetch = FetchType.LAZY,mappedBy =image2048x1536)
@Cascade({CascadeType.ALL})
@JsonIgnore
private SubmissionLauncherImagesVO launcherImage2048x1536;

@OneToOne(fetch = FetchType.LAZY,mappedBy =logo)
@Cascade({CascadeType.ALL})
@JsonIgnore
Private MenuStyleVO menuStyleLogo;






$ b如果L使用以下方法从数据库中加载QuestionVO类hibernate标准代码 - 也加载了MenuStyleVO和ApplicationImageVO的所有惰性字段。



在复杂的用例中,这会导致此查询变得非常慢

  public QuestionVO findMasterAppQuestionById(int id){

Criteria criteria = currentSession()。createCriteria(QuestionVO.class);
criteria.add(Restrictions.eq(id,id));

QuestionVO questionVO =(QuestionVO)criteria.uniqueResult();

返回questionVO;
}

我想知道的是 - 是否可以加载QuestionVO类和它的渴望的领域,并告诉Hibernate忽略其他类的懒惰领域吧?那些需要?

欢呼
达米恩

解决方案

上次我们遇到这样的问题时,我们在父类上使用了一个构造函数,它只使用所需的确定查询字段。

我完全记不清jpql查询中的构造函数是如何工作的,但它必须是这样的:

 从com.package.class中选择新的com.package.class(c.field1,c.field2)c 

请注意,具有相同参数的构造函数必须存在于所需实体中。



优点:$ b​​ $ b - 更好的查询性能;
- 可以与其他参数一起复制;

缺点:$ b​​ $ b - 相当有限,只能对您正在查询的主要实体;
- 包含仅用于确定查询的构造函数,糟糕的设计;

另外,您应该查看JPA的EnttyGraphs。看起来很有前途,但在我们的项目中没有按照我们的期望工作。

顺便说一句,Hibernate已经在性能问题上给了我们很多次,希望这个黑客帮助你,祝你好运!

编辑:



为什么这种模式会对性能问题有所帮助?
基本上,在我之前展示过的示例中,您并未通过Hibernate加载所有内容,只有主实体的两个字段(field1和field2)。如果不使用构造函数,你就无法做到这一点,因为你的查询不会产生所需实体的集合,而是在每个迭代(Object [])的两个对象的集合中。使用构造函数模式创建所需实体的实例,但仅从数据库中选择几个字段,这就是为什么此模式可以帮助您,您只返回所需实体的集合,只有几个字段。


I am experiencing a problem with hibernate and lazy loading of objects. basically I want to load an class which has an eagerly loaded field and not load the lazy fields of child classes

Take the following QuestionVO class

    @Entity
@Table(name = "question")
public class QuestionVO extends BaseDAOVO implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -5867047752936216092L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @Column(name = "questionText", unique = false, nullable = false, length = 4000)
    @Size(min = 3, max = 4000)
    @Pattern(regexp = MobileAppsRegexConstants.GENERAL_ALLOWED_CHARCHTERS, message = "Question Text Not valid.")
    private String questionText;

    @ManyToOne(fetch = FetchType.EAGER)
    @Cascade({ CascadeType.SAVE_UPDATE })
    @JoinColumn(name = "MENU_STYLE_ID", nullable = true)
    private MenuStyleVO menuStyle;

    }

Take the following MenuStyleVO class

   @Entity
@Table(name = "menu_style")
public class MenuStyleVO extends BaseDAOVO implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 3697798179195096156L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @Column(name = "menuStyleName", unique = false, nullable = false, length = 200)
    private String menuStyleName;

    @Column(name = "menuTemplate", unique = false, nullable = false, length = 200)
    private String menuTemplate;

    @OneToOne(fetch = FetchType.LAZY, optional=false)
    @Cascade({ CascadeType.SAVE_UPDATE })
    @JoinColumn(name="logo_id")
    @JsonProperty("logo")
    private ApplicationImageVO logo;


    }

And this ApplicationImageVO class

@Entity
@Table(name = "application_image")
public class ApplicationImageVO extends BaseDAOVO implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -9158898930601867545L;

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "image1242x2208")
    @Cascade({ CascadeType.ALL })
    @JsonIgnore
    private SubmissionLauncherImagesVO launcherImage1242x2208;  

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "image1536x2048")
    @Cascade({ CascadeType.ALL })
    @JsonIgnore
    private SubmissionLauncherImagesVO launcherImage1536x2048;  

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "image2048x1536")
    @Cascade({ CascadeType.ALL })
    @JsonIgnore
    private SubmissionLauncherImagesVO launcherImage2048x1536;  

    @OneToOne(fetch = FetchType.LAZY, mappedBy = "logo")
    @Cascade({ CascadeType.ALL })
    @JsonIgnore
    private MenuStyleVO menuStyleLogo; 

    }

If L load the QuestionVO class from the database using the following hibernate criteria code - all the lazy fields of MenuStyleVO and ApplicationImageVO are also loaded.

On complicated use cases, this results in this query getting very slow

public QuestionVO findMasterAppQuestionById(int id) {

    Criteria criteria = currentSession().createCriteria(QuestionVO.class);
    criteria.add(Restrictions.eq("id", id));

    QuestionVO questionVO  = (QuestionVO) criteria.uniqueResult();

    return questionVO;
}

What I am wondering is - would it be possible to load the QuestionVO class and its eager fields and tell hibernate to ignore lazy fields from the other classes bar those that are needed?

Cheers Damien

解决方案

Last time we faced an issue like this we used a constructor on parent class, which use only the desired fields of determined query.

I can't remember in fully how constructor inside a jpql query works, but it must be something like this:

select new com.package.class(c.field1, c.field2) from com.package.class c

Remember, a constructor with same arguments must be present on the desired entity.

Pros: - Better query perfomance; - Can be replicated with other arguments;

Cons: - Pretty limited, you can only use this hack on the main entity you are querying; - Includes a constructor only for determined query, poor design;

Also, you should take a look on EnttyGraphs of JPA. Seems quite promising, but didn't work as desired in our project.

Btw, Hibernate has put us many times on performance issues, hope this hack help you, good luck!

Edit:

Why this pattern would help in performance issues? Basically, with the example i've showed before, you are not loading everything via Hibernate, only the two fields (field1 and field2) of the main entity. Without using a constructor you shoudn't be able to do that, because your query would not result in a collection of the desired entity, but in a collection of two objects each iteration (Object[]). Using the constructor pattern you are creating instances of the desired entity, but only selecting a few fields from database, and that's why this pattern can help you, you are returning a collection of the desired entity with only a few fields.

这篇关于休眠惰性加载使得标准运行缓慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆