繁体   English   中英

事务注解不能解决 org.hibernate.LazyInitializationException

[英]Transactional annotation doesn't solve org.hibernate.LazyInitializationException

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

  1. 部门
  2. 员工

每个员工在某个部门工作 (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 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);
        }
    }
}

和主要的 class(我不需要 web,所以我使用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();
    }
}

我在 class DepartmentService之前以及它的所有方法之前添加了@Transactional ,但我仍然不断收到以下错误:

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

堆栈跟踪:

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 问题

您需要改用适当的映射或查询,例如在 jpql 中:

select d
from Department d
left join fetch d.employees

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

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

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

@Transactional注释由 AOP 提供支持,那么代理只能处理公共方法。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM