java LazyInitializationException春季启动
我知道有很多类似的线程,但我就是不能从这些线程中找出如何克服这个问题
我有三类车,品牌,颜色。 一辆汽车只有一个品牌和一系列颜色。 布兰德有一份汽车清单。 颜色没有任何关系
为了简单起见,不提供getter、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;
--------------------------------------------------------------------------------
如果我像Earge一样抓取,一切都正常,但我知道这是一种不好的做法,应该改用惰性加载。但我总是遇到LazyInitializationException
我从错误中了解到需要一个会话,但我不知道如何提供会话,因为我正在使用Spring数据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引起。冬眠LazyInitializationException:无法初始化 代理[com.readiness.moita.SrpingJPA.Models.Brand#1]-无会话
# 1 楼答案
因为
Brand
的FetchType
是惰性的,它不会通过调用fetchAll()
自动加载到会话中。要将其自动加载到会话中,您需要:改变
到
前任
如果不想将fetch type设置为eager,那么需要将对toString的调用移动到服务方法Ex
然而,正确的方法是编写一个条件查询或hql
# 2 楼答案
@OneToMany
注释的默认值为FetchType.LAZY
,因此您的集合将被延迟加载为了能够在检索对象后访问该集合,您需要处于事务上下文中(您需要一个打开的会话)
当你打电话时:
在内部创建一个新会话,检索对象,一旦
findAll
方法返回,会话就关闭你应该做的是确保每当你访问汽车对象中的惰性集合时,你有一个打开的会话(这个
toString
就是这么做的)最简单的方法是让另一个服务处理汽车装载,并用
@Transactional
注释showCars
方法。由于处理AOP代理的方式,该方法位于另一个服务中然后你打电话: