如何解决事务注释不能解决org.hibernate.LazyInitializationException
我正在编写一个简单的Spring Data JPA应用程序。我使用MySQL数据库。有两个简单的表:
- 部门
- 员工
每个员工都在某个部门工作(Employee.department_id)。
我有两个实体类:
@Entity
public class Department {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
@Basic(fetch = FetchType.LAZY)
@OneToMany(mappedBy = "department")
List<Employee> employees;
}
@Entity
public class Person {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
private Long id;
@ManyToOne
@JoinColumn
private Department department;
}
存储库:
@Repository
public interface DepartmentRepository extends JpaRepository<Department,Long> {}
@Repository
public interface EmployeeRepository extends JpaRepository<Employee,Long> {}
有一个DepartmentService类:
@Service
@Transactional
public class DepartmentService {
@Autowired
DepartmentRepository departmentRepository;
@Transactional
List<Department> getAll() {
departmentRepository.findAll();
}
@Transactional
void getEmployees() {
for(Department department: getAll()) {
List<Employee> employees = department.getEmployees();
for(Employee employee: employees)
System.out.println(employee);
}
}
}
还有主类(我不需要网络,因此我使用CommandLineRunner
作为控制台应用程序运行该应用程序)
@SpringBootApplication
public class EmployeeDB implements CommandLineRunner {
@Autowired
DepartmentService departmentService;
public static void main(String[] args) {
SpringApplication.run(EmployeeDB.class,args);
}
@Override
public void run(String... args) throws Exception {
departmentService.getEmployees();
}
}
我在类@Transactional
之前及其所有方法之前添加了DepartmentService
,但仍然出现以下错误:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: employeeDB.Department.employees,could not initialize proxy - no Session
Stacktrace:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: employeeDB.Department.employees,could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:602) ~[hibernate-core-5.4.2.Final.jar:5.4.2.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:217) ~[hibernate-core-5.4.2.Final.jar:5.4.2.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:581) ~[hibernate-core-5.4.2.Final.jar:5.4.2.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:148) ~[hibernate-core-5.4.2.Final.jar:5.4.2.Final]
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:303) ~[hibernate-core-5.4.2.Final.jar:5.4.2.Final]
at employeeDB.DepartmentService.getEmployees(DepartmentService.java:25) ~[main/:na]
at employeeDB.EmployeeDB.run(EmployeeDB.java:41) [main/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:795) [spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
... 5 common frames omitted
为什么会出现此错误?我该怎么解决?
解决方法
@Transactional
不应用于获取延迟加载的实体,这将导致n+1 select problem。
您需要改用适当的映射或查询,例如在jpql中:
select d
from Department d
left join fetch d.employees
,
总结以上所有答案和评论:
发生这种情况是因为方法DepartmentService::getEmployees
不是公开的。
我在getEmployees()之前添加了public,这解决了这个问题。
@Transactional
注释由AOP提供支持,因此代理只能处理公共方法。
这意味着@Transactional
实际上并未应用到此方法,并且在读取惰性集合时会话已经关闭。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。