需求:现在有两个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










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