Spring 用于访问事务外部数据的模式
我有一个SpringBoot应用程序,使用SpringDataJPA,hibernate和MySQL作为数据存储 我的应用程序中有3个层:Spring 用于访问事务外部数据的模式,spring,hibernate,spring-data-jpa,spring-transactions,Spring,Hibernate,Spring Data Jpa,Spring Transactions,我有一个SpringBoot应用程序,使用SpringDataJPA,hibernate和MySQL作为数据存储 我的应用程序中有3个层: API服务 应用服务 域服务(带存储库) 应用程序服务的作用是在给定一些业务逻辑的情况下,将支持hibernate的POJO转换为DTO POJO SchoolClass.java @Column Long id; @Column String name; @OneToMany(fetch = FetchType.LAZY, mappedBy = "sc
@Column
Long id;
@Column
String name;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "schoolClass")
List<Book> books;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "schoolClass")
List<Student> students;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "schoolClass")
List<Schedule> schedules;
应用服务
SchoolClassAppService.java
@Autowired
private SchoolClassRepository repository;
@Transactional(readOnly = true)
public SchoolClass getClassById(Long id) {
return repository.findById(id);
}
@Autowired
private SchoolClassService domainService;
public SchoolClassDto getClassById(Long id) {
SchoolClass schoolClass = domainService.getClassById(id);
// convert POJO to DTO;
return SchoolClassDto;
}
我的问题是,当我试图在SchoolClassAppService中访问SchoolClass上的子实体时,它们有时是空的。不是所有的,但三个中有两个可以正常工作,但第三个是空的。我试图将子列表标记为急切获取,但显然,在Hibernate开始抛出异常之前,只能急切获取两个集合,而且总是加载所有对象听起来也不是一个好的做法。我没有得到LazyInitializationException
,只是列表是空的
在返回getter之前,我尝试在域服务方法中的所有列表上调用getter,以便加载POJO的所有数据,但这似乎不是一个干净的做法
是否有任何可用的模式可以使事务边界尽可能靠近持久层,同时即使在事务关闭后仍可以处理数据?不确定为什么您的集合有时是空的,但可能数据就是这样的 我就是为这个用例创建的。实际上,您将JPA实体的DTO定义为接口,并将其应用于查询。它支持映射嵌套的DTO、集合等,基本上是您所期望的一切,而且最重要的是,它将提高您的查询性能,因为它将生成只获取DTO实际需要的数据的查询 您的示例的实体视图可能如下所示
@EntityView(SchoolClass.class)
interface SchoolClassDto {
String getName();
List<BookDto> getBooks();
}
@EntityView(Book.class)
interface BookDto {
// Whatever data you need from Book
}
List<SchoolClassDto> dtos = entityViewManager.applySetting(
EntityViewSetting.create(SchoolClassDto.class),
criteriaBuilderFactory.create(em, SchoolClass.class)
).getResultList();
@EntityView(SchoolClass.class)
接口SchoolClassDto{
字符串getName();
列出getBooks();
}
@EntityView(Book.class)
接口BookDto{
//你们需要从书中得到的任何数据
}
查询可能是这样的
@EntityView(SchoolClass.class)
interface SchoolClassDto {
String getName();
List<BookDto> getBooks();
}
@EntityView(Book.class)
interface BookDto {
// Whatever data you need from Book
}
List<SchoolClassDto> dtos = entityViewManager.applySetting(
EntityViewSetting.create(SchoolClassDto.class),
criteriaBuilderFactory.create(em, SchoolClass.class)
).getResultList();
List dtos=entityViewManager.applySetting(
EntityViewSetting.create(SchoolClassDto.class),
criteriaBuilderFactory.create(em,SchoolClass.class)
).getResultList();
请记住,DTO不应该只是复制您的实体,而应该设计为适合您的特定用例。您是否在事务中检查了
SchoolClassRepository
中的SchoolClassRepository
?您确定所有这些子项都可以正确地拉入吗?如果您没有接受异常,这可能更多地与未按预期进行保存有关,而不是与加载有关。数据已正确保存。如果我在事务中调用所有子列表的getter,那么一旦事务关闭,数据就存在并且也可用。到目前为止,我能提供的线索是,您不能同时获取两个集合。