没有懒惰地初始化一个角色集合

xuy*_*ing 1 spring dao hibernate

@Entity
@Table(name="dt_user" , uniqueConstraints = {@UniqueConstraint(columnNames="user_no"), @UniqueConstraint(columnNames="account")}
)

public class User  implements java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = -8149578944942492965L;
// Fields    

 private long id;
 private String userNo;
 private Set<UserRelative> userRelatives = new HashSet<UserRelative>(0);
// Constructors
/** default constructor */
public User() {
}
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="user")
public Set<UserRelative> getUserRelatives() {
    return this.userRelatives;
}
}
Run Code Online (Sandbox Code Playgroud)

上面是用户实体;下面是另一个UserRelative实体:当想要getUserRelatives()时,问题就出现了.

@Entity
@Table(name="dt_user_relative")
public class UserRelative  implements java.io.Serializable {
/**
 * 
 */
private static final long serialVersionUID = 5035928604641787267L;
// Fields    

 private long id;
 private User user;
.....

@Id @GeneratedValue(strategy=IDENTITY)
@Column(name="id", unique=true, nullable=false)
public long getId() {
    return this.id;
}

public void setId(long id) {
    this.id = id;
}
@ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="user_id")

public User getUser() {
    return this.user;
}

public void setUser(User user) {
    this.user = user;
}
.....
}
Run Code Online (Sandbox Code Playgroud)

我的问题是当我执行此代码时发生错误:我如何通过userNo获取getRelativeTickets()?

userDAO.getUserByNo("10001148").getRelativeTickets().size();
Run Code Online (Sandbox Code Playgroud)
public User getUserByNo(String userNo) {
    // TODO Auto-generated method stub
    String query = "from User t where t.userNo=?1";
    List<User> ls = this.findByQuery(query, userNo);
    if (ls.size() > 0)
        return ls.get(0);
    return null;
}
Run Code Online (Sandbox Code Playgroud)

Deb*_*kia 5

它没有懒惰地初始化集合,因为Hibernate会话在getUserByNo方法结束时被关闭- 数据库连接不再可用,并且对象图被分离.现在,当您调用getRelativeTickets()方法时,Hibernate无法获取关联,因为会话不再可用,并且Hibernate不会隐式地打开新连接(或会话)来延迟加载关联.

建议的解决方案是确保User在从getUserByNo方法返回之前完全初始化所有需要的关联.在HQL中,您可以指定使用from子句急切地获取关联fetch join:

String query = "from User t left join fetch t.relativeTickets where t.userNo=?1";
Run Code Online (Sandbox Code Playgroud)

这将返回UserrelativeTickets关联完全初始化.这样,关联的初始化发生在单个SQL语句中,因此不需要再次命中DB来初始化关联.