gpt4 book ai didi

java - LazyInitializationException Spring Boot

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:00:51 29 4
gpt4 key购买 nike

我知道那里有很多类似的线程,但我只是无法从这些线程中弄清楚如何解决这个问题。

我有 3 个类 Car、Brand、Color。一辆汽车只有一个品牌和一个颜色列表。品牌有一份汽车 list 。颜色没有任何关系。

为简单起见,未提供 Getters、Setter、ToString 和构造函数。我能够将对象保存到数据库中,并且数据库已经填充。

-------------------------------------------- ----------------------------------

@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。

我从错误中了解到需要一个 session ,但我不知道如何提供一个,因为我正在使用 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] - 无 session

最佳答案

@OneToMany 注释的默认值是 FetchType.LAZY,因此您的集合会延迟加载。

为了能够在检索到对象后访问集合,您需要处于事务上下文中(您需要一个打开的 session )

当你打电话时:

carRepository.findAll();

内部会创建一个新 session ,检索对象,一旦 findAll 方法返回, session 就会关闭。

您应该做的是确保每当您访问 Car 对象中的惰性集合(toString 所做的)时都有一个打开的 session 。

最简单的方法是让另一个服务处理汽车装载并用 @Transactional 注释 showCars 方法,由于 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);
}

关于java - LazyInitializationException Spring Boot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53836776/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com