当前位置:编程学习 > JAVA >>

关于hibernate3N+1的问题,用了left join fetch还是无效

hibernate3中,有三个表,关系多对多,对应的类关系如下
Action类
package com.op.crm.persist.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

/**
 * Action entity. @author MyEclipse Persistence Tools
 */
@Entity
@Table(name = "NFK_ACTION", schema = "NFKORA")
public class Action implements java.io.Serializable {

// Fields

/**
 * 
 */
private static final long serialVersionUID = 1L;
private String actionId;
private String actionName;
private String action;
private String insertUser;
private String insertTime;
private String updateUser;
private String updateTime;
private Set<Role> roles = new HashSet<Role>(0);

// Constructors

/** default constructor */
public Action() {
}

// Property accessors
@Id
@Column(name = "ACTION_ID", unique = true, nullable = false, length = 20)
public String getActionId() {
return this.actionId;
}
public void setActionId(String actionId) {
this.actionId = actionId;
}
@Column(name = "ACTION_NAME", nullable = false, length = 50)
public String getActionName() {
return this.actionName;
}
public void setActionName(String actionName) {
this.actionName = actionName;
}
@Column(name = "ACTION", nullable = false, length = 300)
public String getAction() {
return this.action;
}
public void setAction(String action) {
this.action = action;
}
@Column(name = "INSERT_USER", nullable = false, length = 20)
public String getInsertUser() {
return this.insertUser;
}
public void setInsertUser(String insertUser) {
this.insertUser = insertUser;
}

@ManyToMany(mappedBy="actions")
public Set<Role> getRoles() {
return roles;
}

public void setRoles(Set<Role> roles) {
this.roles = roles;
}

}

Role类
package com.op.crm.persist.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

/**
 * Role entity. @author MyEclipse Persistence Tools
 */
@Entity
@Table(name = "NFK_ROLE", schema = "NFKORA")
public class Role implements java.io.Serializable {

// Fields

/**
 * 
 */
private static final long serialVersionUID = 1L;
private String roleId;
private String roleName;
private String insertUser;
private String insertTime;
private String updateUser;
private String updateTime;
private Set<Action> actions = new HashSet<Action>(0);
private Set<User> users = new HashSet<User>(0);

// Constructors

/** default constructor */
public Role() {
}

// Property accessors
@Id
@Column(name = "ROLE_ID", unique = true, nullable = false, length = 20)
public String getRoleId() {
return this.roleId;
}

public void setRoleId(String roleId) {
this.roleId = roleId;
}

@Column(name = "ROLE_NAME", nullable = false, length = 50)
public String getRoleName() {
return this.roleName;
}

public void setRoleName(String roleName) {
this.roleName = roleName;
}

@ManyToMany
@JoinTable(name="NFK_ROLE_ACTION",
joinColumns=@JoinColumn(name="ROLE_ID"),
inverseJoinColumns=@JoinColumn(name="ACTION_ID"))
public Set<Action> getActions() {
return actions;
}

public void setActions(Set<Action> actions) {
this.actions = actions;
}

@ManyToMany(mappedBy="roles")
public Set<User> getUsers() {
return users;
}

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

}

User类
package com.op.crm.persist.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

/**
 * User entity. @author MyEclipse Persistence Tools
 */
@Entity
@Table(name = "NFK_USER", schema = "NFKORA")
public class User implements java.io.Serializable {

// Fields

/**
 * 
 */
private static final long serialVersionUID = 1L;
private String userId;
private String password;
private String name;
private String sex;
private String mobile;
private String qq;
private String email;
private String address;
private String insertUser;
private String insertTime;
private String updateUser;
private String updateTime;
private Set<Role> roles = new HashSet<Role>(0);
private Set<Group> groups = new HashSet<Group>(0);
private String rePassword;

// Constructors

/** default constructor */
public User() {
}

// Property accessors
@Id
@Column(name = "USER_ID", unique = true, nullable = false, length = 20)
public String getUserId() {
return this.userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

@Column(name = "PASSWORD", nullable = false, length = 300)
public String getPassword() {
return this.password;
}

public void setPassword(String password) {
this.password = password;
}

@Column(name = "NAME", nullable = false, length = 30)
public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

@Column(name = "SEX", nullable = false, length = 1)
public String getSex() {
return this.sex;
}

public void setSex(String sex) {
this.sex = sex;
}

@Column(name = "MOBILE", nullable = false, length = 20)
public String getMobile() {
return this.mobile;
}

public void setMobile(String mobile) {
this.mobile = mobile;
}

@Column(name = "QQ", length = 20)
public String getQq() {
return this.qq;
}

public void setQq(String qq) {
this.qq = qq;
}

@ManyToMany
@JoinTable(name="NFK_USER_ROLE",
joinColumns=@JoinColumn(name="USER_ID"),
inverseJoinColumns=@JoinColumn(name="ROLE_ID"))
public Set<Role> getRoles() {
return roles;
}

public void setRoles(Set<Role> roles) {
this.roles = roles;
}


}


现在,我需要查询出所有的Role,并且Role对象中的users和roles对象都有内容
于是我利用hql这样查询
public List<Role> selectRoles() throws Exception {
List<Role> results = (List<Role>)this.getHibernateTemplate().find("select distinct r from Role r left outer join fetch r.actions left outer join fetch r.users");
return results;
}

执行这个方法后,show_sql显示出一条sql语句
select distinct role0_.ROLE_ID as ROLE1_0_0_, action2_.ACTION_ID as ACTION1_1_1_, user4_.USER_ID as USER1_2_2_, role0_.INSERT_TIME as INSERT2_0_0_, role0_.INSERT_USER as INSERT3_0_0_, role0_.ROLE_NAME as ROLE4_0_0_, role0_.UPDATE_TIME as UPDATE5_0_0_, role0_.UPDATE_USER as UPDATE6_0_0_, action2_.ACTION as ACTION1_1_, action2_.ACTION_NAME as ACTION3_1_1_, action2_.INSERT_TIME as INSERT4_1_1_, action2_.INSERT_USER as INSERT5_1_1_, action2_.UPDATE_TIME as UPDATE6_1_1_, action2_.UPDATE_USER as UPDATE7_1_1_, actions1_.ROLE_ID as ROLE1_0__, actions1_.ACTION_ID as ACTION2_0__, user4_.ADDRESS as ADDRESS2_2_, user4_.EMAIL as EMAIL2_2_, user4_.INSERT_TIME as INSERT4_2_2_, user4_.INSERT_USER as INSERT5_2_2_, user4_.MOBILE as MOBILE2_2_, user4_.NAME as NAME2_2_, user4_.PASSWORD as PASSWORD2_2_, user4_.QQ as QQ2_2_, user4_.SEX as SEX2_2_, user4_.UPDATE_TIME as UPDATE11_2_2_, user4_.UPDATE_USER as UPDATE12_2_2_, users3_.ROLE_ID as ROLE2_1__, users3_.USER_ID as USER1_1__ from NFKORA.NFK_ROLE role0_ left outer join NFK_ROLE_ACTION actions1_ on role0_.ROLE_ID=actions1_.ROLE_ID left outer join NFKORA.NFK_ACTION action2_ on actions1_.ACTION_ID=action2_.ACTION_ID left outer join NFK_USER_ROLE users3_ on role0_.ROLE_ID=users3_.ROLE_ID left outer join NFKORA.NFK_USER user4_ on users3_.USER_ID=user4_.USER_ID

这是我预期中的,他把所有级联的对象都left join了
但是,我访问这些级联属性时,又产生了N条查询语句
select roles0_.ACTION_ID as ACTION2_1_, roles0_.ROLE_ID as ROLE1_1_, role1_.ROLE_ID as ROLE1_0_0_, role1_.INSERT_TIME as INSERT2_0_0_, role1_.INSERT_USER as INSERT3_0_0_, role1_.ROLE_NAME as ROLE4_0_0_, role1_.UPDATE_TIME as UPDATE5_0_0_, role1_.UPDATE_USER as UPDATE6_0_0_ from NFK_ROLE_ACTION roles0_ left outer join NFKORA.NFK_ROLE role1_ on roles0_.ROLE_ID=role1_.ROLE_ID where roles0_.ACTION_ID=?
select roles0_.ACTION_ID as ACTION2_1_, roles0_.ROLE_ID as ROLE1_1_, role1_.ROLE_ID as ROLE1_0_0_, role1_.INSERT_TIME as INSERT2_0_0_, role1_.INSERT_USER as INSERT3_0_0_, role1_.ROLE_NAME as ROLE4_0_0_, role1_.UPDATE_TIME as UPDATE5_0_0_, role1_.UPDATE_USER as UPDATE6_0_0_ from NFK_ROLE_ACTION roles0_ left outer join NFKORA.NFK_ROLE role1_ on roles0_.ROLE_ID=role1_.ROLE_ID where roles0_.ACTION_ID=?
select roles0_.USER_ID as USER1_1_, roles0_.ROLE_ID as ROLE2_1_, role1_.ROLE_ID as ROLE1_0_0_, role1_.INSERT_TIME as INSERT2_0_0_, role1_.INSERT_USER as INSERT3_0_0_, role1_.ROLE_NAME as ROLE4_0_0_, role1_.UPDATE_TIME as UPDATE5_0_0_, role1_.UPDATE_USER as UPDATE6_0_0_ from NFK_USER_ROLE roles0_ left outer join NFKORA.NFK_ROLE role1_ on roles0_.ROLE_ID=role1_.ROLE_ID where roles0_.USER_ID=?
select roles0_.USER_ID as USER1_1_, roles0_.ROLE_ID as ROLE2_1_, role1_.ROLE_ID as ROLE1_0_0_, role1_.INSERT_TIME as INSERT2_0_0_, role1_.INSERT_USER as INSERT3_0_0_, role1_.ROLE_NAME as ROLE4_0_0_, role1_.UPDATE_TIME as UPDATE5_0_0_, role1_.UPDATE_USER as UPDATE6_0_0_ from NFK_USER_ROLE roles0_ left outer join NFKORA.NFK_ROLE role1_ on roles0_.ROLE_ID=role1_.ROLE_ID where roles0_.USER_ID=?

这四条明显是多余的
如何去掉这四条多余的sql Hibernate N+1 fetch
补充:Java ,  Java EE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,