![](/img/trans.png)
[英]hibernate lazy initialization issue: LazyInitializationException: failed to lazily initialize a collection of role
[英]Hibernate lazy initialization - failed to lazily initialize a collection
每當我嘗試從“用戶”表中檢索數據時,都會收到以下錯誤消息,我已經在網上搜索了很多東西,試圖找出可能出問題的地方,但找不到任何東西,所以有人可以通過告訴我什么來幫助我失蹤/我在這里錯了嗎?
錯誤:
錯誤:org.hibernate.LazyInitializationException-無法延遲初始化角色集合:com.domain.crm.domain.Role.users,未關閉任何會話或會話org.hibernate.LazyInitializationException:無法延遲初始化角色集合: com.domain.crm.domain.Role.users,沒有會話或會話被關閉
用戶類別:
@Entity
@Table(name="COM_USER")
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="USER_ID")
private Long id;
@Column(name="USER_NAME",nullable=false,length=25,unique=true)
private String userName;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="ROLE_ID",nullable=false)
private Role role;
}
角色類別:
@Entity
@Table(name="COM_ROLE")
public class Role {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ROLE_ID")
private Long id;
@Column(name="ROLE",nullable=false,unique=false)
private Integer Role;
@OneToMany(mappedBy="role")
private Set<User> users=new HashSet<User>();
}
用戶DAO類被調用以收集所有用戶的方法:
public List<User> getUsers(Long page, Long pageSize) {
Long start = (page-1)*pageSize;
return sessionfactory.getCurrentSession().createQuery("from User u ").setFirstResult(start.intValue()).setMaxResults(pageSize.intValue()).list();
}
用戶服務類方法:
@Transactional
public List<User> getUsers(Long page, Long pageSize) {
return userdao.getUsers(page, pageSize);
}
控制器類調用方法:
@RequestMapping(value = "/users/list-user-data")
@ResponseBody
public UserListData listUserData(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
UserListData listData = new UserListData();
String page = request.getParameter("page");
Long pageLong = Long.parseLong(page);
Long pageSize = (long)15;
List<User> searchResults = iuserservice.getUsers(pageLong, pageSize);
if( searchResults != null ){
List<List<Object>> aaData = new ArrayList<List<Object>>();
List<Object> listItem = null;
for( User u : searchResults ){
listItem = new ArrayList<Object>();
listItem.add(u.getLastName());
listItem.add(u.getFirstName());
listItem.add(u.getUserName());
listItem.add(u.getEmail());
listItem.add(u.getRole());
aaData.add(listItem);
}
listData.setAaData(aaData);
}
int totalCount = iuserservice.getAllUsersCount().intValue();
System.out.println("Number of records in DB: "+totalCount);
listData.setiTotalRecords(totalCount);
return listData;
}
最后是我的pom.xml依賴項:
<properties>
<java-version>1.6</java-version>
<org.springframework-version>3.1.0.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.9</org.aspectj-version>
<org.slf4j-version>1.5.10</org.slf4j-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.1.3.RELEASE</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!-- Mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.0.Final</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Commons DBCP -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
謝謝你的時間
我在這里發布示例。 基本想法是僅具有3個數據庫表,其中2個用於實體User
和Role
,最后一個作為映射表,即user_role
。 在用戶表中,我們存儲用戶詳細信息,在角色表中,我們存儲角色ID和名稱,在映射表中,我們將用戶映射到角色。 我從自己的項目中復制。 我的類擴展的BaseEntity只是一個映射的超類,它具有每個實體的常規字段,例如id,創建/修改日期等。
用戶實體
@Entity
@Table(name = "user_t")
public class User extends BaseEntity {
@Column(name = "username", nullable = false, unique = true)
private String userName;
@Column(name = "password", nullable = false)
private String password;
@ManyToMany
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> role = new HashSet<Role>();
// getters & setters
}
角色實體
@Entity(name = "role_t")
public class Role extends BaseEntity {
@Column(name = "role_name", nullable = false)
private String roleName;
public Role() {
}
public Role(String roleName) {
this.roleName = roleName;
}
// getters & setters
}
請注意,默認情況下ManyToMany
使用預先獲取類型,因此我們不需要設置它。 現在,當我從服務中查詢User
實體時。 role
集合不會被獲取。 如果我需要獲取屬於該用戶的角色,則需要通過查詢手動獲取它們。 我使用Spring Data JPA存儲庫,例如,對於單個結果,查詢看起來像這樣。
UserRepository類
public interface UserRepository extends JpaRepository<User, Long> {
@Query("SELECT u FROM User u JOIN FETCH u.role WHERE u.userName = (:userName)")
public User findByUserNameAndFetchRoles(@Param("userName") String userName);
@Query("FROM User u JOIN FETCH u.role")
public List<User> getAllUsersAndFetchRoles(); // **query that you would use!**
}
然后,在UserService
層中,您將使用該存儲庫/ DAO查詢。 對我而言,使用急切的角色提取是必要的,因為每次我想查詢用戶列表時,我都不需要獲取角色,因為在我的真實項目中,角色也具有一組權限,並且只是不值得查詢您不需要的東西。
問題是默認情況下@OneToMany
關聯是惰性的,並且在您調用getUsers()
,會話已在服務方法中關閉。 解決它的一種方法是急於加載子記錄。 但是要小心,因為這可能會導致您加載過多的數據,這會減慢數據速度並殺死內存。 例如,在您的Role
實體中,如果將其設置為熱切加載Users
:
@OneToMany(mappedBy="role", fetch = FetchType.EAGER)
private Set<User> users=new HashSet<User>();
}
每當您加載Role
,Hibernate都會加載其所有子Users
。
處理您的情況的一種方法是在@Transactional
方法中對服務進行所有工作,這應確保會話仍處於打開狀態(最好使用服務方法@Transactional
而不是DAO)
@Transactional
public UserListData getUserListData(Long page, Long pageSize) {
List<User> searchResults = userdao.getUsers(page, pageSize);
UserListData listData = new UserListData();
if( searchResults != null ){
List<List<Object>> aaData = new ArrayList<List<Object>>();
List<Object> listItem = null;
for( User u : searchResults ){
listItem = new ArrayList<Object>();
listItem.add(u.getLastName());
listItem.add(u.getFirstName());
listItem.add(u.getUserName());
listItem.add(u.getEmail());
listItem.add(u.getRole());
aaData.add(listItem);
}
listData.setAaData(aaData);
}
return listData;
}
您正在某個地方(上面的代碼中未顯示)正在訪問Role
實體中的users
集合字段的某些方法。
您不能從具有渴望獲取類型的同一事務中加載Roles
集合。 要解決此問題,您需要手動初始化Roles集合或對查詢進行fetch join
存。 這應該為您解決。
public List<User> getUsers(Long page, Long pageSize) {
Long start = (page-1)*pageSize;
return sessionfactory.getCurrentSession().createQuery("FROM User u JOIN FETCH u.role ").setFirstResult(start.intValue()).setMaxResults(pageSize.intValue()).list();
}
另外,我建議User
和Roles
之間具有ManyToMany
關系,並使用映射表。 使用以下內容,並從角色實體中刪除用戶集。 復制角色表上的角色記錄是多余的。
@ManyToMany
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> role = new HashSet<Role>();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.