如何在hibernate中只获取bean的所需属性?

时间:2012-02-09 07:16:14

标签: hibernate criteria hibernate-mapping hibernate-criteria

我正在为我的应用程序使用Hibernate 3.5.6。在这个应用程序中,我使用hbm.xml文件将我的POJO映射到数据库表列。

在这个应用程序中,我有User bean,如下所示。

public class User {
// login info
private long id;
private String type; 

private String userName; 
private String password; 
private String securityQuestionStr; 
private String securityAnswer; 

// personal info
private String firstName; 
private String middleName;
private String lastName; 

/**
 * <b>{@link GenderType} gender</b>
 */
private GenderType gender;

private Date dateOfBirth; 

// other related info
/**
 * <b>{@link UserType} userType</b>
 */
private UserType userType; 

// contact info
private Long mobileNo; 
private Long businessPhoneNo; 
private Long homePhoneNo; 
private Long faxNo; 
private String email; 
private String alternateEmail;

/**
 * <b>{@link RegistrationStatus} userStatus</b>
 */
private RegistrationStatus userStatus;

/**
 * <b>{@link Post} posts</b>
 */
private String securityAnswerHash;
private String passwordHash;
private String encryptedPassword;
private String encryptedSecurityAnswer;
private String nationality; 

private String portal;
private float version;
private Date createdDate;
private User createdUser;
private String createdIP;
private Date lastModifiedDate;
private User lastModifiedUser;
private String lastModifiedIP;
private boolean recordStatus; 
private String publicKey;
private String certificateName;
private String signPublicKey;
private String signCertificateName;
private boolean isEtoken;

public long getId() {
    return id;
}
public void setId(long id) {
    this.id = id;
}
public String getType() {
    return type;
}
public void setType(String type) {
    this.type = type;
}
public String getUserName() {
    return userName;
}
public void setUserName(String userName) {
    this.userName = userName;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
public String getSecurityQuestionStr() {
    return securityQuestionStr;
}
public void setSecurityQuestionStr(String securityQuestionStr) {
    this.securityQuestionStr = securityQuestionStr;
}
public String getSecurityAnswer() {
    return securityAnswer;
}
public void setSecurityAnswer(String securityAnswer) {
    this.securityAnswer = securityAnswer;
}
public String getFirstName() {
    return firstName;
}
public void setFirstName(String firstName) {
    this.firstName = firstName;
}
public String getMiddleName() {
    return middleName;
}
public void setMiddleName(String middleName) {
    this.middleName = middleName;
}
public String getLastName() {
    return lastName;
}
public void setLastName(String lastName) {
    this.lastName = lastName;
}
public GenderType getGender() {
    return gender;
}
public void setGender(GenderType gender) {
    this.gender = gender;
}
public Date getDateOfBirth() {
    return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
    this.dateOfBirth = dateOfBirth;
}
public UserType getUserType() {
    return userType;
}
public void setUserType(UserType userType) {
    this.userType = userType;
}
public Long getMobileNo() {
    return mobileNo;
}
public void setMobileNo(Long mobileNo) {
    this.mobileNo = mobileNo;
}
public Long getBusinessPhoneNo() {
    return businessPhoneNo;
}
public void setBusinessPhoneNo(Long businessPhoneNo) {
    this.businessPhoneNo = businessPhoneNo;
}
public Long getHomePhoneNo() {
    return homePhoneNo;
}
public void setHomePhoneNo(Long homePhoneNo) {
    this.homePhoneNo = homePhoneNo;
}
public Long getFaxNo() {
    return faxNo;
}
public void setFaxNo(Long faxNo) {
    this.faxNo = faxNo;
}
public String getEmail() {
    return email;
}
public void setEmail(String email) {
    this.email = email;
}
public String getAlternateEmail() {
    return alternateEmail;
}
public void setAlternateEmail(String alternateEmail) {
    this.alternateEmail = alternateEmail;
}
public RegistrationStatus getUserStatus() {
    return userStatus;
}
public void setUserStatus(RegistrationStatus userStatus) {
    this.userStatus = userStatus;
}
public String getSecurityAnswerHash() {
    return securityAnswerHash;
}
public void setSecurityAnswerHash(String securityAnswerHash) {
    this.securityAnswerHash = securityAnswerHash;
}
public String getPasswordHash() {
    return passwordHash;
}
public void setPasswordHash(String passwordHash) {
    this.passwordHash = passwordHash;
}
public String getEncryptedPassword() {
    return encryptedPassword;
}
public void setEncryptedPassword(String encryptedPassword) {
    this.encryptedPassword = encryptedPassword;
}
public String getEncryptedSecurityAnswer() {
    return encryptedSecurityAnswer;
}
public void setEncryptedSecurityAnswer(String encryptedSecurityAnswer) {
    this.encryptedSecurityAnswer = encryptedSecurityAnswer;
}
public String getNationality() {
    return nationality;
}
public void setNationality(String nationality) {
    this.nationality = nationality;
}
public String getPortal() {
    return portal;
}
public void setPortal(String portal) {
    this.portal = portal;
}
public float getVersion() {
    return version;
}
public void setVersion(float version) {
    this.version = version;
}
public Date getCreatedDate() {
    return createdDate;
}
public void setCreatedDate(Date createdDate) {
    this.createdDate = createdDate;
}
public User getCreatedUser() {
    return createdUser;
}
public void setCreatedUser(User createdUser) {
    this.createdUser = createdUser;
}
public String getCreatedIP() {
    return createdIP;
}
public void setCreatedIP(String createdIP) {
    this.createdIP = createdIP;
}
public Date getLastModifiedDate() {
    return lastModifiedDate;
}
public void setLastModifiedDate(Date lastModifiedDate) {
    this.lastModifiedDate = lastModifiedDate;
}
public User getLastModifiedUser() {
    return lastModifiedUser;
}
public void setLastModifiedUser(User lastModifiedUser) {
    this.lastModifiedUser = lastModifiedUser;
}
public String getLastModifiedIP() {
    return lastModifiedIP;
}
public void setLastModifiedIP(String lastModifiedIP) {
    this.lastModifiedIP = lastModifiedIP;
}
public boolean isRecordStatus() {
    return recordStatus;
}
public void setRecordStatus(boolean recordStatus) {
    this.recordStatus = recordStatus;
}
public String getPublicKey() {
    return publicKey;
}
public void setPublicKey(String publicKey) {
    this.publicKey = publicKey;
}
public String getCertificateName() {
    return certificateName;
}
public void setCertificateName(String certificateName) {
    this.certificateName = certificateName;
}
public String getSignPublicKey() {
    return signPublicKey;
}
public void setSignPublicKey(String signPublicKey) {
    this.signPublicKey = signPublicKey;
}
public String getSignCertificateName() {
    return signCertificateName;
}
public void setSignCertificateName(String signCertificateName) {
    this.signCertificateName = signCertificateName;
}
public boolean isEtoken() {
    return isEtoken;
}
public void setEtoken(boolean isEtoken) {
    this.isEtoken = isEtoken;
}

}

现在,当我想从数据库中获取User时,我使用了条件或获取或加载方法。 但是当我看到由hibernate生成的查询时,查询长度太高。这是因为我在User bean中有38个属性。由于所有属性都是String类型和原语(没有任何属性是Has-的类型)另一个bean类)

但我的实际所需id仅为10-12或者一次只能有20个属性。我不希望hibernate获取fetch User bean上的每个属性。

为此我已经看过HQL我只能在构造函数中提供我想要获取的属性数。 如下所示:

Query query = session
            .createQuery("select new User(id, userName) from User where id=?");
    query.setParameter(0, 1l);

它只会触发查询以获取id和UserName,因此查询长度很短,而且我只获得了我需要的属性。

但是每次使用不同类型的属性编写查询非常困难,并且还需要在POJO类中需要相同的签名构造函数。 当User类中的某些集合和其他bean同时想要获取时,它会更加困难。

所以我想知道是否有任何其他方法可以限制hibernate仅针对所有属性(字符串或基本类型)触发查询。

2 个答案:

答案 0 :(得分:1)

这看起来像是对我的过早优化,特别是如果您的查询只返回实例中的一个User实例。

不仅如此,它实际上非常令人困惑,因为查询不返回完整的User:它返回一个User,几乎所有字段都设置为null,这可能会破坏类的不变量,并且没有调用者知道某个字段在数据库中是否真的为空,或者只是因为您的查询选择不加载它而为空的方式。

我首先会测量加载这些字段是否确实会导致性能问题,并且只会优化是否存在性能问题。我会使用专用的UserDTO,它只包含查询实际加载的字段。您还可以查看fetch groups,它可以启用延迟加载属性,但正如参考手册所述:

  

请注意,这主要是营销功能;优化行   读取比列读取的优化要重要得多。   但是,只加载类的某些属性可能很有用   极端的情况。例如,当遗留表有数百个   列和数据模型无法改进。

答案 1 :(得分:1)

您可以编写一个实用程序,为您准备此类动态查询。

DataBaseUtil.createPropertySpecificQuery(Clazz entity, String[] properties, String[] conditionParams, String[] conditionOperators){} write a logic to build query.

如果在POJO中有关联集合,则可以添加使用连接的逻辑。

我觉得它很有用,而且比DTO更喜欢它,因为它们减少了很多管理它们进行转换,改变等的麻烦。