主要问题是如何在不违反SOLID原则的情况下将DTO转换为实体,将实体转换为Dtos。
例如,我们有这样的json:
{ id: 1,
name: "user",
role: "manager"
}
DTO是:
public class UserDto {
private Long id;
private String name;
private String roleName;
}
和实体是:
public class UserEntity {
private Long id;
private String name;
private Role role
}
public class RoleEntity {
private Long id;
private String roleName;
}
还有一个有用的Java8DTO转换模式。
但是在他们的例子中,没有OneTo多项关系。为了创建UserEntity,我需要使用道层(服务层)按角色获取角色名称。我可以将UserRepository(或UserService)注入到Conconeter中吗?因为似乎转换器组件将打破SRP,它必须只转换,不能知道服务或存储库。
转换器示例:
@Component
public class UserConverter implements Converter<UserEntity, UserDto> {
@Autowired
private RoleRepository roleRepository;
@Override
public UserEntity createFrom(final UserDto dto) {
UserEntity userEntity = new UserEntity();
Role role = roleRepository.findByRoleName(dto.getRoleName());
userEntity.setName(dto.getName());
userEntity.setRole(role);
return userEntity;
}
....
在卷积器类中使用存储库好吗?或者我应该创建另一个服务/组件,负责从DTO创建实体(如UserFactory)?
就个人而言,转换器应该位于控制器和服务之间,DTO唯一应该担心的是服务层中的数据以及如何向控制器公开哪些信息。
controllers <-> converters <-> services ...
在您的情况下,您可以使用JPA在持久层填充用户的角色。
如果您有一个服务层,那么使用它来进行转换或将任务委托给转换器将更有意义
理想情况下,转换器应该只是转换器:映射器对象,而不是服务
现在,如果逻辑不太复杂且转换器不可重复使用,您可以将服务处理与映射处理混合使用,在这种情况下,您可以将转换器
前缀替换为服务
而且,如果只让服务与存储库通信,看起来会更好
否则图层会变得模糊,设计也会变得凌乱:我们真的不知道是谁调用了谁。
我会这样做:
controller -> service -> converter
-> repository
或自行执行转换的服务(转换不太复杂且不可重用):
controller -> service -> repository
老实说,我讨厌DTO,因为它们只是重复的数据
我之所以介绍它们,是因为客户在信息方面的需求与实体表示不同,而且定制类(在本例中不是重复类)更清晰
尽量将转换与其他层分离:
public class UserConverter implements Converter<UserEntity, UserDto> {
private final Function<String, RoleEntity> roleResolver;
@Override
public UserEntity createFrom(final UserDto dto) {
UserEntity userEntity = new UserEntity();
Role role = roleResolver.apply(dto.getRoleName());
userEntity.setName(dto.getName());
userEntity.setRole(role);
return userEntity;
}
}
@Configuration
class MyConverterConfiguration {
@Bean
public Converter<UserEntity, UserDto> userEntityConverter(
@Autowired RoleRepository roleRepository
) {
return new UserConverter(roleRepository::findByRoleName)
}
}
您甚至可以定义一个自定义的转换器
正如其他一些人指出的那样,这种抽象隐藏了应用程序的一部分,当用于集合时,这部分应用程序的性能可能非常差(因为数据库查询通常可以批处理。我建议你定义一个转换器
如果您想在定义转换器时获得更多的舒适性,请查看MapSTRt或ModelMapper。最后但并非最不重要的是给datus一个机会(免责声明:我是作者),它可以让你流畅地定义你的映射,而没有任何隐含的功能:
@Configuration
class MyConverterConfiguration {
@Bean
public Mapper<UserDto, UserEntity> userDtoCnoverter(@Autowired RoleRepository roleRepository) {
Mapper<UserDto, UserEntity> mapper = Datus.forTypes(UserDto.class, UserEntity.class)
.mutable(UserEntity::new)
.from(UserDto::getName).into(UserEntity::setName)
.from(UserDto::getRole).map(roleRepository::findByRoleName).into(UserEntity::setRole)
.build();
return mapper;
}
}
(此示例在转换
集合时仍会遇到数据库瓶颈
我认为这将是最可靠的方法,但给定的上下文/场景正遭受着无法处理的依赖性和性能影响,这让我认为强制使用SOLID可能是一个坏主意。这是一种权衡
我正在使用带有bootrepackagegradle的springboot来构建发布jar文件。我的项目需要在交付给客户之前混淆代码。我尝试了proguard和其他一些工具,但出现了许多问题。我想知道如何为spring boot配置这些工具。 我用这些配置试过ProGuard 但是生成的jar无法运行
我正在学习如何使用Docker与一个Spring Boot应用程序。我遇到了一个小障碍,我希望有人能看到这个问题。我的应用程序严重依赖于环境特定属性文件中设置的@value。在我的/src/main/resources中,我有三个属性文件 应用程序.属性 应用程序-local.properties 应用程序-prod.properties 我通常用:java-jar-dspring.profile
我正在使用Spring Boot 1.2.7和Thymeleaf。 所有html页面都在文件夹中,当我说
我正在用Thymeleaf构建一个Spring Boot应用程序。我的模板(视图)和静态文件夹都在src/main/Resources/静态和src/main/Resources/tem板下。当我通过main方法(使用eclipse)运行应用程序时,一切都很好。但是,我已经按照说明创建了一个war文件,当我将其部署到Tomcat 7时——静态内容丢失了,只显示了Thymeleaf html模板。
我想在我的spring boot项目中使用Kafka Streams实时处理。所以我需要Kafka Streams配置,或者我想使用KStreams或KTable,但我在互联网上找不到示例。 我做了制作人和消费者现在我想流实时。
我试图在spring boot应用程序中构建shaded jar,但是遇到了一些问题。我不知道我做错了什么。我还阅读了以下链接,但没有运气maven-shade-plugin错误:无法在org . Apache . maven . plugins . shade . resource . manifestresourceformer中找到“resource”的setter、adder或field