我正在开始我的项目。因此,我试图设计一种架构,避免Hibernate LazyInitializationExceptions的出现。到目前���止,我的applicationContext.xml文件中有以下内容:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>/WEB-INF/hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
</props>
</property>
<property name="eventListeners">
<map>
<entry key="merge">
<bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/>
</entry>
</map>
</property>
</bean>
<bean id="dao" class="info.ems.hibernate.HibernateEMSDao" init-method="createSchema">
<property name="hibernateTemplate">
<bean class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
<property name="flushMode">
<bean id="org.springframework.orm.hibernate3.HibernateAccessor.FLUSH_COMMIT" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
</property>
</bean>
</property>
<property name="schemaHelper">
<bean class="info.ems.hibernate.SchemaHelper">
<property name="driverClassName" value="${database.driver}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="hibernateDialect" value="${hibernate.dialect}"/>
<property name="dataSourceJndiName" value="${database.datasource.jndiname}"/>
</bean>
</property>
</bean>
hibernate.cfg.xml文件:
<hibernate-configuration>
<session-factory>
<mapping class="info.ems.models.User" />
<mapping class="info.ems.models.Role" />
</session-factory>
</hibernate-configuration>
Role.java文件:
@Entity
@Table(name="ROLE")
@Access(AccessType.FIELD)
public class Role implements Serializable {
private static final long serialVersionUID = 3L;
@Id
@Column(name="ROLE_ID", updatable=false, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name="USERNAME")
private String username;
@Column(name="ROLE")
private String role;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
还有User.java文件:
@Entity
@Table(name = "USER")
@Access(AccessType.FIELD)
public class User implements UserDetails, Serializable {
private static final long serialVersionUID = 2L;
@Id
@Column(name = "USER_ID", updatable=false, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "USERNAME")
private String username;
@Column(name = "PASSWORD")
private String password;
@Column(name = "NAME")
private String name;
@Column(name = "EMAIL")
private String email;
@Column(name = "LOCKED")
private boolean locked;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, targetEntity = Role.class)
@JoinTable(name = "USER_ROLE", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") })
private Set<Role> roles;
@Override
public GrantedAuthority[] getAuthorities() {
List<GrantedAuthorityImpl> list = new ArrayList<GrantedAuthorityImpl>(0);
for (Role role : roles) {
list.add(new GrantedAuthorityImpl(role.getRole()));
}
return (GrantedAuthority[]) list.toArray(new GrantedAuthority[list.size()]);
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return !isLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isLocked() {
return locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
}
HibernateEMSDao有两个方法用于保存和从数据库加载用户信息:
public void saveUser(final User user) {
getHibernateTemplate().execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException, SQLException {
session.flush();
session.setCacheMode(CacheMode.IGNORE);
session.save(user);
session.flush();
return null;
}
});
}
public User getUser(final Long id) {
return (User) getHibernateTemplate().execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException, SQLException {
return session.get(User.class, id);
}
});
}
现在我测试了一下,如果我将HibernateEMSDao#getUser
实现为:
public User getUser(final Long id) {
getHibernateTemplate().load(User.class, id);
}
我得到了LazyInitializationException - session is closed的错误。但第一种方法却运行良好。因此,我需要建议以避免在不久的将来出现此异常。任何小片段的信息都是可赞赏的。
感谢和问候。
注:我在重新启动服务器后收到该错误。
编辑:代码已添加:
public void saveUser(final User user) {
Session session = getSession();
Transaction transaction = session.beginTransaction();
session.save(user);
transaction.commit();
session.close();
}
public User getUser(final Long id) {
Session session = getSession();
session.enableFetchProfile("USER-ROLE-PROFILE");
User user = (User) session.get(User.class, id);
session.disableFetchProfile("USER-ROLE-PROFILE");
session.close();
return user;
}