事务注释不能解决org.hibernate.LazyInitializationException [英] Transactional annotation doesn't solve org.hibernate.LazyInitializationException

查看:67
本文介绍了事务注释不能解决org.hibernate.LazyInitializationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个简单的Spring Data JPA应用程序.我使用MySQL数据库.有两个简单的表:

I'm writing a simple Spring Data JPA application. I use MySQL database. There are two simple tables:

  1. 部门
  2. 员工

每个员工都在某个部门工作(Employee.department_id).

Each employee works in some department (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类:

There is a DepartmentService class:

@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 将其作为控制台应用程序运行):

And the main class (I don't need web, so I use CommandLineRunner to run the application as a console application):

@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();
    }
}

我在类 DepartmentService 之前以及所有方法之前添加了 @Transactional ,但仍然出现以下错误:

I added @Transactional before the class DepartmentService and also before all its methods, but I still keep getting the following error:

 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: employeeDB.Department.employees, could not initialize proxy - no Session

Stacktrace:

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

为什么会出现此错误?我该怎么解决?

Why do I get this error? How can I solve it?

推荐答案

总结以上所有答案和评论:

发生这种情况是因为方法 DepartmentService :: getEmployees 不是公开的.

This happens because method DepartmentService::getEmployees is not public.

我在getEmployees()之前添加了public,这解决了这个问题.

I added public before getEmployees() and this sloved the problem.

@Transactional 注释由AOP提供支持,因此代理只能处理公共方法.

@Transactional annotation is powered by AOP, then only public methods could be handled by proxy.

这意味着 @Transactional 实际上并未应用到此方法,并且在读取惰性集合时会话已经关闭.

This means that @Transactional is not actually applied to this method and the session is already closed an the moment of reading lazy collection.

这篇关于事务注释不能解决org.hibernate.LazyInitializationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆