java - LazyInitializationException Spring Boot
问题描述
我知道那里有很多类似的线程,但我只是无法从这些线程中弄清楚如何克服这个问题。
我有 3 类汽车,品牌,颜色。一辆车只有一个品牌和一个颜色列表。品牌有一个汽车清单。颜色没有任何关系。
为简单起见,没有提供 Getter、Setter、ToString 和 Constructors。我能够将对象保存到数据库中,并且数据库已经填充。
-------------------------------------------------- ------------------------------
@Entity
@Table(catalog = "spring_project")
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String model;
@ManyToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable( name = "car_color", catalog = "spring_project",
joinColumns = { @JoinColumn(name = "car_id") },
inverseJoinColumns = { @JoinColumn(name = "colors_id") }
)
private List<Color> colors = new ArrayList<>();
@ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name="brand_id", referencedColumnName="id")
private Brand brand;
-------------------------------------------------- ------------------------------
@Entity
@Table(catalog = "spring_project")
public class Brand {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "brand", fetch = FetchType.LAZY)
private List<Car> cars = new ArrayList<>();
-------------------------------------------------- ------------------------------
@Entity
@Table(catalog = "spring_project")
public class Color {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
-------------------------------------------------- ------------------------------
如果我像 Eager 一样获取,一切都运行良好,但我知道这是一种不好的做法,应该使用延迟加载。但我不断收到 LazyInitializationException。
我从错误中了解到需要一个会话,但我不知道如何提供一个会话,因为我正在使用 Spring Data JPA,我也不应该在哪里声明......
@SpringBootApplication
public class SrpingJpaApplication {
private static final Logger log =
LoggerFactory.getLogger(SrpingJpaApplication.class);
public static void main(String[] args) {
SpringApplication.run(SrpingJpaApplication.class, args);
}
@Bean
public CommandLineRunner demo(CarRepository carRepository,
ColorRepository colorRepository,
BrandRepository brandRepository) {
return (args) -> {
log.info("Reads all cars....");
for (Car c : carRepository.findAll()) {
System.out.println(c.toString());
}
};
}
}
太感谢了。
已编辑----->>>
在 c.toString(); 上抛出错误。
错误:原因:org.hibernate.LazyInitializationException:无法初始化代理 [com.readiness.moita.SrpingJPA.Models.Brand#1] - 没有会话
解决方案
@OneToMany
注释的默认设置是FetchType.LAZY
延迟加载您的集合。
为了能够在您检索对象后访问该集合,您需要处于事务上下文中(您需要一个打开的会话)
你打电话时:
carRepository.findAll();
在内部创建一个新会话,检索对象,并且一旦findAll
方法返回会话就关闭。
您应该做的是确保您在访问 Car 对象中的惰性集合时有一个打开的会话(toString
确实如此)。
最简单的方法是让另一个服务处理汽车装载,并使用方法在另一个服务中注释showCars
方法,@Transactional
因为处理 AOP 代理的方式。
@Service
public CarService {
final CarRepository carRepository;
public CarService(CarRepository carRepository) {
this.carRepository = carRepository;
}
@Transactional
public void showCars(String... args) {
for (Car c : carRepository.findAll()) {
System.out.println(c.toString());
}
}
}
然后你打电话:
@Bean
public CommandLineRunner demo(CarService carService) {
return (args) -> service.showCars(args);
}
推荐阅读
- netlogo - 从列表中挑选元素
- c++ - 在 Visual Studio 中构建 wxWidgets-3.1.2 项目时如何修复“找不到 setup.h”错误?
- c - C:按顺序计算 2 个表达式,然后返回第一个
- javascript - 将对象更新为新对象的实例
- c# - 当前上下文中不存在名称“进程”
- javascript - 在不停止应用程序的情况下拦截 400 错误请求
- c++ - 递归导致程序崩溃,但 while 循环中的相同概念并非来自 C++ 析构函数
- javascript - 如何修复“TypeError:无法设置属性‘已批准’为空”?
- c++ - 使用 QTableView 和 QgsCanvas 在应用程序上崩溃
- python - Python中的有效回文解决方案不起作用