关于在测试类中,懒加载问题导致加载了主类之后,在测试类中引用集合类出现错误的问题:
主要原因是因为:hibernate的事物是给了spring管理,而测试类中写的代码,是不归spring管理的,把代码转移到service中去执行进行
在测试类:EmployeeServiceTest中直接运行
@Test
public void testEmployeeInDept(){
try {
Department department = DepartMentService.getDepartmentByName("ixin开发部");
Set<Employee> set = department.getEmps();
for (Employee employee : set) {
System.out.println(employee.getName());
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
出现错误:
/**
* 因为在测试代码中,事物是不归spring管理的,所以执行:
* Department department = DepartMentService.getDepartmentByName("ixin开发部");
* 的时候,还是有事物的,处于spring管理的事物范围之内,而执行完成之后,就断了。
* 所以在:Set<Employee> set = department.getEmps();这个执行代码中,是获取不到内容的
* 会报异常:
* Hibernate:
select
department0_.id as id1_0_,
department0_.name as name2_0_
from
department department0_
where
department0_.name=?
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.xltx.productinfograb.domain.entity.Department.emps, could not initialize proxy - no Session
*/
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "department")
public class Department implements Serializable{
private Long id;
private String name;
private Set<Employee> emps = new HashSet<>();
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name", length = 20)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 总结:mappedBy属性跟xml配置文件里的inverse一样。在一对多或一对一的关系映射中,如果不表明mappedBy属性,默认是由本方维护外键。但如果两方都由本方来维护的话,会多出一些update语句,性能有一定的损耗。
解决的办法就是在一的一方配置上mappedBy属性,将维护权交给多的一方来维护,就不会有update语句了。
至于为何要将维护权交给多的一方,可以这样考虑:要想一个国家的领导人记住所有人民的名字是不可能的,但可以让所有人民记住领导人的名字!
注意,配了mappedBy属性后,不要再有@JoinColumn,会冲突!
* @return
*/
@OneToMany(fetch = FetchType.LAZY, mappedBy = "dept")
public Set<Employee> getEmps() {
return emps;
}
public void setEmps(Set<Employee> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + ", emps=" + emps
+ "]";
}
public Department() {
super();
// TODO Auto-generated constructor stub
}
}
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "employee")
public class Employee implements Serializable{
private Long id;
private String name;
private float salary;
private String email;
private Department dept;
public Employee() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", salary=" + salary
+ ", email=" + email + ", dept=" + dept + "]";
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name", length = 30)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "salary")
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
@Column(name = "email", length = 30)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "dept", nullable = false)
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
}
import java.io.Serializable;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.xltx.orm.dao.BaseDao;
import com.xltx.productinfograb.domain.entity.Department;
import com.xltx.productinfograb.domain.entity.Employee;
@Service
@Transactional(readOnly = false, rollbackFor = Exception.class)
public class DepartMentService {
@Autowired
BaseDao baseDao;
public Department add(Department department){
Serializable id = baseDao.add(department);
department = baseDao.get(Department.class, id);
return department;
}
public Department getDepartmentByName(String departmentName){
String hql = "From Department d where d.name = ?";
Department department = baseDao.getFirstByHql(hql, departmentName);
return department;
}
public void testEmployeeInDept(){
Department department = getDepartmentByName("xxx开发部");
Set<Employee> set = department.getEmps();
for (Employee employee : set) {
System.out.println(employee.getName());
}
}
}
package com.xltx.test;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.xltx.productinfograb.domain.entity.Department;
import com.xltx.productinfograb.domain.entity.Employee;
import com.xltx.productinfograb.service.impl.DepartMentService;
import com.xltx.productinfograb.service.impl.EmployeeService;
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
@ContextConfiguration({"classpath:applicationContext.xml"}) //加载配置文件
public class EmployeeServiceTest {
@Autowired
EmployeeService employeeService;
@Autowired
DepartMentService DepartMentService;
@Test
public void add(){
Department dept = DepartMentService.getDepartmentByName("ixin开发部");
Employee employee = new Employee();
employee.setDept(dept);
employee.setEmail("13076684@qq.com");
employee.setName("何冠宏");
employee.setSalary(100000.00f);
employeeService.add(employee);
Employee employee2 = new Employee();
employee2.setDept(dept);
employee2.setEmail("111@qq.com");
employee2.setName("22何冠宏");
employee2.setSalary(200000.00f);
employeeService.add(employee2);
Employee employee3 = new Employee();
employee3.setDept(dept);
employee3.setEmail("33@qq.com");
employee3.setName("33何冠宏");
employee3.setSalary(300000.00f);
employeeService.add(employee3);
}
/**
* 因为在测试代码中,事物是不归spring管理的,所以执行:
* Department department = DepartMentService.getDepartmentByName("ixin开发部");
* 的时候,还是有事物的,处于spring管理的事物范围之内,而执行完成之后,就断了。
* 所以在:Set<Employee> set = department.getEmps();这个执行代码中,是获取不到内容的
* 会报异常:
* Hibernate:
select
department0_.id as id1_0_,
department0_.name as name2_0_
from
department department0_
where
department0_.name=?
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.xltx.productinfograb.domain.entity.Department.emps, could not initialize proxy - no Session
*/
@Test
public void testEmployeeInDept(){
try {
Department department = DepartMentService.getDepartmentByName("ixin开发部");
Set<Employee> set = department.getEmps();
for (Employee employee : set) {
System.out.println(employee.getName());
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* 将代码放到处于spring管理的service中去执行之后,就不会有问题了
*/
@Test
public void test1(){
try {
DepartMentService.testEmployeeInDept();
System.out.println("");
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}