简体   繁体   English

在多对多关系中改善Hibernete的表现

[英]Improving Hibernete performance in many-to-many relationship

I have two tables connected with many-to-many relationship. 我有两个表与多对多关系连接。 Database is set on another server and I see really big performance problem when I'm trying to get informations about one of the records if these informations include total count of the second table. 数据库设置在另一台服务器上,当我试图获取有关其中一条记录的信息时,如果这些信息包含第二个表的总计数,我会发现真正的大性能问题。

First bean: 第一豆:

package dbaccess.beans.newsletter;

import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Column;
import javax.persistence.Table;

import dbaccess.beans.RegisteredUser;

@Entity
@Table(name="NEWSLETTER_LIST")
public class NewsletterList {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "G1")
    @SequenceGenerator(name = "G1", sequenceName = "NEWSLETTER_LIST_SEQ", allocationSize = 1, initialValue= 1)
    @Column(name = "LIST_ID", unique = true, nullable = false)
    private Long listID;

    @Column(name = "LIST_NAME", nullable = false, length = 50)
    private String listName;

    @ManyToMany(fetch = FetchType.LAZY, cascade = {})
    @JoinTable(name = "NEWSLETTERLISTS_USERS", joinColumns = { 
            @JoinColumn(name = "LIST_ID", nullable = false) }, 
            inverseJoinColumns = { @JoinColumn(name = "USER_ID", nullable = false) })
    private Set<RegisteredUser> users = new HashSet<RegisteredUser>(0);

    public Long getListID() {
        return listID;
    }

    public void setListID(Long listID) {
        this.listID = listID;
    }

    public Set<RegisteredUser> getUsers() {
        return users;
    }

    public void setUsers(Set<RegisteredUser> users) {
        this.users = users;
    }

}

Second bean: 第二豆:

package dbaccess.beans;

import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Column;
import javax.persistence.Table;

import dbaccess.beans.newsletter.NewsletterList;

@Entity
@Table(name="USER")
public class RegisteredUser {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "G1")
    @SequenceGenerator(name = "G1", sequenceName = "USER_SEQ", allocationSize = 1, initialValue= 1)
    @Column(name = "USER_ID", unique = true, nullable = false)
    private Long usrID;

    @Column(name = "GIVENNAME", length = 20)
    private String usrGivenName;

    @Column(name = "FAMILYNAME", length = 20)
    private String usrFamilyName;

    @ManyToMany(fetch = FetchType.EAGER, mappedBy = "users", cascade = {})
    public Set<NewsletterList> newsletterList = new HashSet<NewsletterList>();

    public Long getUsrID() {
        return usrID;
    }

    public void setUsrID(Long usrID) {
        this.usrID = usrID;
    }

    public String getUsrGivenName() {
        return usrGivenName;
    }

    public void setUsrGivenName(String usrGivenName) {
        this.usrGivenName = usrGivenName;
    }

    public String getUsrFamilyName() {
        return usrFamilyName;
    }

    public void setUsrFamilyName(String usrFamilyName) {
        this.usrFamilyName = usrFamilyName;
    }

    public Set<NewsletterList> getNewsletterList() {
        return newsletterList;
    }

    public void setNewsletterList(Set<NewsletterList> newsletterList) {
        this.newsletterList = newsletterList;
    }

    @Override
    public String toString() {
        return "RegisteredUser[usrID=" + usrID + ", usrGivenName=" + usrGivenName + ", usrFamilyName=" + usrFamilyName + "]";
    }

}

And the problem is when I try to execute this piece of code: 问题是当我尝试执行这段代码时:

session = dbService.getSessionFactory().openSession();
Criteria c = session.createCriteria(NewsletterList.class);
c.add(Restrictions.eq("listID", listID));
List<NewsletterList> newsletterList = (List<NewsletterList>) c.list();

//below is most expensive
newsletterList.get(0).getUsers().size()

Is there any way to improve this performance? 有没有办法改善这种表现? Thanks in advance. 提前致谢。

PS When I have approx. PS当我有约。 70 users in one list, request to above code takes approx 5-6 seconds! 一个列表中的70个用户,对上述代码的请求大约需要5-6秒!

newsletterList.get(0).getUsers().size() makes Hibernate load all the users registered to the newsletter, only to get the number of registered users. newsletterList.get(0).getUsers().size()使得Hibernate加载注册到时事通讯的所有用户,只获得注册用户的数量。

Use an ad hoc HQL query to count the number of registered users: 使用临时HQL查询来计算注册用户的数量:

select count(user.usrID) from RegisteredUser user
inner join user.newsletterList newsLetter
where newsLetter.listID = :listId

Note that 5-6 seconds to execute the above code is way too much, though. 请注意,执行上述代码5-6秒的方式太多了。 You probably need to check if there is an index placed on the join columns of the join table. 您可能需要检查连接表的连接列上是否放置了索引。

Also note that you could simply use session.get(NewsLetter.class, listId) to get the list by ID. 另请注意,您只需使用session.get(NewsLetter.class, listId)即可按ID获取列表。

And finally, everything would be easier and more readable if your IDs were all named id . 最后,如果您的ID都是id ,那么一切都会更简单,更易读。

You might want to try using the Hibernate Criteria API to query for the number of users on a specific newsletter. 您可能希望尝试使用Hibernate Criteria API来查询特定时事通讯上的用户数。 It would look roughly like this: 看起来大致如下:

Criteria crit = session.createCriteria(RegisteredUser.class);
crit.setProjection(Projections.rowCount());
crit.add(Restrictions.eq("listID", listID));
return (Long) crit.uniqueResult(); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM