数据传输对象设计模式中的java保留Hibernate延迟加载
我通常在持久层使用Hibernate处理三层应用程序,并注意不要在表示层使用域模型类。这就是我使用DTO (Data Transfer Object)
设计模式的原因
但我在实体dto映射中总是进退两难。无论我是丢失了延迟加载功能,还是通过引入过滤器来调用或不调用域模型getters
,在代码中造成了复杂性
示例:考虑与实体用户相对应的DTO UserDto
public UserDto toDto(User entity, OptionList... optionList) {
if (entity == null) {
return null;
}
UserDto userDto = new UserDto();
userDto.setId(entity.getId());
userDto.setFirstname(entity.getFirstname());
if (optionList.length == 0 || optionList[0].contains(User.class, UserOptionList.AUTHORIZATION)) {
IGenericEntityDtoConverter<Authorization, AuthorizationDto> authorizationConverter = converterRegistry.getConverter(Authorization.class);
List<AuthorizationDto> authorizations = new ArrayList<>(authorizationConverter.toListDto(entity.getAuthorizations(), optionList));
userDto.setAuthorizations(authorizations);
...
}
OptionList
用于过滤映射并映射所需内容
虽然最后一个解决方案允许延迟加载,但它非常繁重,因为必须在服务层中指定optionList
在DTO设计模式中保留延迟加载是否有更好的解决方案强>
# 1 楼答案
我不确定您为什么希望延迟加载,但我猜是因为您的
UserDto
通过optionList
配置提供多个表示? 我不知道您的表示层代码是什么样子的,但我想您对optionList
中的每个元素都有很多if-else代码用不同的表示法,比如子类,怎么样?我问这个是因为我想建议尝试一下。下面是一个适合您的领域的小代码示例
这些是dto,其中包含一些关于映射到实体模型的元数据。下面是用法:
现在,如果你像
service.findByName("someName", EntityViewSetting.create(SimpleUserView.class))
一样使用它,它将生成一个如下的查询如果你使用另一个视图,比如
service.findByName("someName", EntityViewSetting.create(AuthorizationUserView.class))
,它会生成除了能够摆脱手动对象映射之外,由于使用了优化的查询,性能还会提高
# 2 楼答案
对于相同的实体持久状态,我不喜欢在某些执行路径中有未初始化的对象字段,而在其他情况下,这些字段也可能被初始化。这会导致头痛,无法维持:
null
也是一个有效选项(因此不会导致NullPointer),则可能意味着数据已被删除,并且可能会触发意外的删除业务规则,而数据实际上仍然存在李>我宁愿创建接口和/或类的DTO层次结构,从
UserDto
开始。所有实际的dto实现字段都被填充以反映持久状态:如果有数据,dto的字段不为空因此,您只需要询问服务层您想要哪个Dto实现:
然后在服务层,您可以有:
注册不同的构建器,创建并初始化各种UserDto实现