0

我有两个以多对多关系连接的表。数据库设置在另一台服务器上,当我尝试获取有关其中一个记录的信息时,如果这些信息包括第二个表的总数,我会看到非常大的性能问题。

第一个豆子:

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;
    }

}

第二个豆:

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 + "]";
    }

}

问题是当我尝试执行这段代码时:

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()

有什么办法可以提高这种性能吗?提前致谢。

PS当我有大约。一个列表中有 70 个用户,请求上述代码大约需要 5-6 秒!

4

2 回答 2

2

newsletterList.get(0).getUsers().size()使 Hibernate 加载所有注册到时事通讯的用户,只获取注册用户的数量。

使用 ad hoc HQL 查询来统计注册用户的数量:

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

请注意,执行上述代码的时间为 5-6 秒,但实在是太长了。您可能需要检查连接表的连接列上是否放置了索引。

另请注意,您可以简单地使用session.get(NewsLetter.class, listId)通过 ID 获取列表。

最后,如果您的 ID 都被命名为id.

于 2013-04-05T14:08:25.683 回答
0

您可能想尝试使用Hibernate Criteria API来查询特定时事通讯的用户数量。它看起来大致是这样的:

Criteria crit = session.createCriteria(RegisteredUser.class);
crit.setProjection(Projections.rowCount());
crit.add(Restrictions.eq("listID", listID));
return (Long) crit.uniqueResult(); 
于 2013-04-05T14:09:38.297 回答