2025年怎么进行不同bean之间的转换?

怎么进行不同bean之间的转换?需求 现在有两个 bean 一个 User 一个 UserCopy 其中 User 的属性有 staId username password data UserCopy 的属性有多种场景 此时要求我们将 User 的属性值 copy 到 UserCopy 对象上 此时我们有几种做法

大家好,我是讯享网,很高兴认识大家。

需求:现在有两个bean,一个User,一个UserCopy。其中User的属性有:staId、username、password、data;UserCopy的属性有多种场景。

此时要求我们将User的属性值copy到UserCopy对象上,此时我们有几种做法?

2、使用java自带的BeanUtils(反射)

3、使用spring自带的BeanUtils

4、使用MapStruct、JMapper、ModelMapper、dozer、Orika等第三方工具包(推荐)

推荐使用使用MapStruct、JMapper,各种第三方包性能比较看:https://www.cnblogs.com/javaguide/p/11861749.html

 

1、使用java自带的Beanutils

User:

@Data public class User { private int staId; private String username; private String password; private Date data; }
讯享网

UserCopy:

讯享网@Data public class UserCopy { private int staId; private String username; private String password; private Date data; }

1、使用java自带的BeanUtils(导import org.apache.commons.beanutils.BeanUtils; )

@SpringBootApplication public class DemoApp { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { SpringApplication.run(DemoApp.class,args); //1、设置User对象 User user = new User(); user.setData(new DateTime()); user.setPassword(""); user.setStaId(123); user.setUsername("张三"); //2、调用copyProperties方法将user赋值给userCopy对象 UserCopy userCopy = new UserCopy(); BeanUtils.copyProperties(userCopy,user); //打印copy结果: System.out.println(userCopy); } } 

结果:正常赋值

当然你也可以单独对某个属性进行赋值:https://www.cnblogs.com/wardensky/p/4716981.html

2、如果此时将其中的一个属性改了,将UserCopy对象的staId改为id,或者将int类型改为String类型。

重新运行:发现一个都没赋值成功

或者在UserCopy中多加一个属性aa。

重新运行:

总结:java自带的Beanutils只可以对属性名+类型+属性个数完全相同的两个对象进行copy操作。其他都不能赋值成功

2、使用spring的BeanUtils

1、当属性名+类型+属性个数完全相同时:

讯享网@SpringBootApplication public class DemoApp { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { SpringApplication.run(DemoApp.class,args); //1、设置User对象 User user = new User(); user.setData(new DateTime()); user.setPassword(""); user.setStaId(123); user.setUsername("张三"); //2、调用copyProperties方法将user赋值给userCopy对象 UserCopy userCopy = new UserCopy(); //(1)java自带的 //BeanUtils.copyProperties(userCopy,user); //(2)spring的.(注意参数是位置颠倒的) BeanUtils.copyProperties(user,userCopy); //打印copy结果: System.out.println(userCopy); } }

赋值成功:

2、当属性名不同/属性个数不同/属性类型不同时:

(1)属性名不同:将UserCopy的staId改为id。

重新运行:发现只有id这个属性没赋值成功,而其他相同的属性还是赋值成功了

(2)类型不同时,此时只修改UserCopy的staId为String类型

重新运行:此时也只是没赋值不同类型的属性

(3)、属性个数不同时,向UserCopy对象中加入aa这个属性

重新运行:发现匹配的属性都赋值了。

结论:spring自带的BeanUtils可以进行部分赋值,该部分赋值且只能赋值类型+属性名一致的属性。

3、使用MapStruct进行赋值

这里定义两个实体类UserRole、Role(其中Role是UserRole的一个属性),一个dto类UserRoleDto(即两个实体类要赋值到该dto对象)

——————————————————————UserRole类 @AllArgsConstructor @Data public class UserRole { private Long id; private String username; private String password; private String phoneNum; private String email; private Role role; } ————————————————————Role类 @AllArgsConstructor @Data public class Role { private Long id; private String roleName; private String description; } ————————————————————————UserRoleDto @Data public class UserRoleDto { / * 用户id 从UserRole中赋值 */ private Long userId; / * 用户名 从UserRole中赋值 */ private String name; / * 角色名 从Role中赋值 */ private String roleName; }

导入依赖pom:

<properties> <mapstruct.version>1.2.0.Final</mapstruct.version> </properties> <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-jdk8</artifactId> <version>${mapstruct.version}</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${mapstruct.version}</version> </dependency> </dependencies>

编写映射关系的配置接口:

/ * @Mapper 定义这是一个MapStruct对象属性转换接口,在这个类里面规定转换规则 * 在项目构建时,会自动生成改接口的实现类,这个实现类将实现对象属性值复制 */ @Mapper public interface UserRoleMapper { / * 获取该类自动生成的实现类的实例 * 接口中的属性都是 public static final 的 方法都是public abstract的 */ UserRoleMapper INSTANCES = Mappers.getMapper(UserRoleMapper.class); / * 这个方法就是用于实现对象属性复制的方法 * * @Mapping 用来定义属性复制规则 source 指定源对象属性 target指定目标对象属性 * * @param user 这个参数就是源对象,也就是需要被复制的对象 * @return 返回的是目标对象,就是最终的结果对象 */ @Mappings({ @Mapping(source = "id", target = "userId"), @Mapping(source = "username", target = "name"), @Mapping(source = "role.roleName", target = "roleName") }) UserRoleDto toUserRoleDto(UserRole user); } 

测试映射接口是否成功:

@SpringBootApplication public class DemoApp { public static void main(String[] args) throws InvocationTargetException, IllegalAccessException { SpringApplication.run(DemoApp.class,args); //1、初始化UserRole和Role两个对象 Role role = new Role(2L, "administrator", "超级管理员"); UserRole user = new UserRole(1L, "zhangsan", "12345", "", "", role); //2、调用映射配置接口的实例的toUserRoleDto方法 UserRoleDto userRoleDto = UserRoleMapper.INSTANCES.toUserRoleDto(user); //3、打印查看映射情况 System.out.println(userRoleDto); } }

打印结果:可以看到都映射成功。

此时如果我们把roleName的类型改成int,发现是不行的。而当我把roleName的值从administrator改为6666时,却打印成功了。为什么?

其实在MapStruct中如果是基本数据类型,会帮我们进行隐式转换,但其要求是该值可以进行转换,像上面的类型为String且值为administrator,此时要转换为int是转不过来的,而当我改为6666则可以进行转换。

2、自定义

自定义类型转换

有时候,在对象转换的时候可能会出现这样一个问题,就是源对象中的类型是Boolean类型,而目标对象类型是String类型,这种情况可以通过@Mapper的uses属性来实现:

@Data @NoArgsConstructor @AllArgsConstructor public class Customer { private Long id; private String name; private Boolean isDisable; } @Data public class CustomerDto { private Long id; private String customerName; private String disable; } 

定义转换规则的类:

public class BooleanStrFormat { public String toStr(Boolean isDisable) { if (isDisable) { return "Y"; } else { return "N"; } } public Boolean toBoolean(String str) { if (str.equals("Y")) { return true; } else { return false; } } } 

定义Mapper,@Mapper( uses = { BooleanStrFormat.class}),注意,这里的users属性用于引用之前定义的转换规则的类:

@Mapper( uses = { BooleanStrFormat.class}) public interface CustomerMapper { CustomerMapper INSTANCES = Mappers.getMapper(CustomerMapper.class); @Mappings({ @Mapping(source = "name", target = "customerName"), @Mapping(source = "isDisable", target = "disable") }) CustomerDto toCustomerDto(Customer customer); } 

这样子,Customer类中的isDisable属性的true就会转变成CustomerDto中的disable属性的yes。

3、将映射配置接口交给spring容器管理

在配置接口上加上componentModel = "spring",即代表加入容器中(编译出来的是一个@Component注解)

@Mapper(componentModel = "spring") public interface CustomerMapper { CustomerMapper INSTANCES = Mappers.getMapper(CustomerMapper.class); @Mappings({ @Mapping(source = "name", target = "customerName"), @Mapping(source = "isDisable", target = "disable") }) CustomerDto toCustomerDto(Customer customer); } 

然后我们就可以在要使用的地方对该接口进行注入使用。

MapStruct还可以进行String和其他基本类型的转换,String和Date类型的转换,string和boolean的转换(自定义),Map、枚举的映射等,详细可以看:https://www.cnblogs.com/gotten/p/13052911.html

 

小讯
上一篇 2025-02-17 19:13
下一篇 2025-01-07 20:43

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/28105.html