为什么在春季启动应用程序的一对多关系中子集合为空?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么在春季启动应用程序的一对多关系中子集合为空?相关的知识,希望对你有一定的参考价值。
我使用mysql,JPA,Web依赖项创建一个Spring启动应用程序,并在Spring启动的.properties文件中手动配置我的数据库设置。我通过编译,并成功启动应用程序,添加一条记录是正常的。
但是,我使用方法'findAll(Pageable pageable)'我遇到了问题,就是这样
Could not write JSON: failed to lazily initialize a collection of role,could not initialize proxy - no Session
我感到困惑,我开始调试我的代码,最后我发现结果的子集合为null,它包含一个错误,这是
"Exception occurred: com.sun.jdi.InvocationException occurred invoking method.."
我尝试了很多来修复我的代码,但没有用。谁能帮我?
实体关系是一个简单的一对多:TeacherInfo实体和ClassInfo实体,教师管理多个类,就这么简单。
这是我的应用程序的输入点:
@SpringBootApplication(exclude= {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class,
DataSourceAutoConfiguration.class
})
@EnableTransactionManagement
public class OrmTestApplication {
public static void main(String[] args) {
SpringApplication.run(OrmTestApplication.class, args);
}
}
数据库属性设置如下:
spring.datasource.primary.url=jdbc:mysql://localhost:3306/ormtest?useSSL=false
spring.datasource.primary.username=root
spring.datasource.primary.password=BlaNok2700
spring.datasource.primary.driver-class-name = com.mysql.jdbc.Driver
hibernate.hbm2ddl.auto = update
hibernate.show-sql = true
我的数据库配置java代码在这里:
Configuration
@EnableJpaRepositories(basePackages = "com.lanjian.ormtest.repositories", entityManagerFactoryRef = "primaryEntityManagerFactory", transactionManagerRef = "primaryTransactionManager")
public class PrimaryDbConfig {
@Autowired
private Environment env;
@Bean
@ConfigurationProperties(prefix="spring.datasource.primary")
public DataSourceProperties primaryDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource primaryDataSource() {
DataSourceProperties dbProperty = primaryDataSourceProperties();
return DataSourceBuilder.create()
.driverClassName(dbProperty.getDriverClassName())
.url(dbProperty.getUrl())
.username(dbProperty.getUsername())
.password(dbProperty.getPassword())
.build();
}
@Bean
public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(primaryDataSource());
factory.setPackagesToScan("com.lanjian.ormtest.entities");
factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
jpaProperties.put("hibernate.show-sql", env.getProperty("hibernate.show-sql"));
factory.setJpaProperties(jpaProperties);
return factory;
}
@Bean
public PlatformTransactionManager primaryTransactionManager() {
EntityManagerFactory factory = primaryEntityManagerFactory().getObject();
return new JpaTransactionManager(factory);
}
}
我的REST控制器方法在这里:
@Autowired
private TeacherRepository teacherRepository;
@GetMapping("/page")
public Page<TeacherInfo> page(Pageable pageable){
Page<TeacherInfo> list = teacherRepository.findAll(pageable);
return list;
}
发生了什么在我开始我的应用程序,并使用邮递员发送请求后,我得到了这个:got a 500 error
我调试我的代码,发现这个:child collection is null在图片中,'classes'是一个列表集合,但它是null,我不明白。
这是我定义的TeacherInfo实体
@Entity
@Table(name = "teacher")
public class TeacherInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private byte age;
private boolean male;
@OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY, mappedBy="chargedTeacher")
private List<ClassInfo> classes = new ArrayList<>();
public void initialize() {
for (ClassInfo classInfo : classes) {
classInfo.setChargedTeacher(this);
for (StudentInfo studentInfo : classInfo.getStudents()) {
studentInfo.setClassInfo(classInfo);
}
}
}
//Setters and Getters}
这是我定义的ClassInfo实体
@Entity
@Table(name = "class_info")
public class ClassInfo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int capacity;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "teacher_id",nullable=false)
@JsonIgnore
private TeacherInfo chargedTeacher;
@OneToMany(cascade = CascadeType.ALL,fetch=FetchType.LAZY,mappedBy="classInfo")
private List<StudentInfo> students = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getCapacity() {
return capacity;
}
public void setCapacity(int capacity) {
this.capacity = capacity;
}
public TeacherInfo getChargedTeacher() {
return chargedTeacher;
}
public void setChargedTeacher(TeacherInfo chargedTeacher) {
this.chargedTeacher = chargedTeacher;
}
public List<StudentInfo> getStudents() {
return students;
}
public void setStudents(List<StudentInfo> students) {
this.students = students;
}
}
我认为问题可能来自Transactionality和JPA Fetching类型。
您的存储库方法不是使用事务调用的,这意味着事务处于方法调用的边界(可能没有错)。 Spring返回一个带有对象的页面,但是当它尝试序列化它们时,事务就消失了,所以无法访问子节点。
我建议将JPA关系作为EAGER获取,允许所有对象在事务结束时出现在存储库结果中。
编辑:回答评论@Bean public PlatformTransactionManager primaryTransactionManager(EntityManagerFactory factory){return new JpaTransactionManager(factory); }
以上是关于为什么在春季启动应用程序的一对多关系中子集合为空?的主要内容,如果未能解决你的问题,请参考以下文章