从简单的 java 对象 (POJO) getter 映射到 setter 的好方法是什么?可以使用反射吗?
What is a good way for getter to setter mapping from simple java objects (POJOs). Can is use reflection for it?
嗨,我有两个 java 对象,它们彼此独立,但共享相同的 getter 和 setter 方法。例如,我有一个 UserEntity 和 UserDTO 对象,我会将所有 getter 值从 UserEntity 映射到所有 setter 的 UserDTO。
做这类事情的最佳方法是什么?我更喜欢用 java 反射来做,但如果外面有一些有用的框架实现,我现在也想这样做。
使用反射不使用外部库
您好,您可以检查源对象的所有 getter,并尝试在目标对象上找到所有相应的 setter。以下方法应该可以做到:
/**
* Maps all getter of the source to all corresponding setter of the target
* @param target
* target object which should be set
* @param source
* source object to read from
* @return
* returns mapped target object or null if some error occurred
*/
private Object getterToSetter(Object target, Object source) {
try {
for(Method m: source.getClass().getMethods()){
// try to find for all getters in the source the corresponding setter on the target
if(m.getName().startsWith("get")){
Method setter;
try {
setter = target.getClass().getMethod("set" + m.getName().substring(3), m.getReturnType());
setter.invoke(target,m.invoke(source));
} catch (NoSuchMethodException e) {
//ignored target just haven't a setter for this field
}
}
}
// return value to support builder pattern
return target;
}catch (IllegalAccessException| InvocationTargetException e){
e.printStackTrace();
}
return null;
}
这是一个完整的Main.class示例,说明它是如何工作的:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author Andreas Hauschild
*/
public class Main {
public static void main(String[] args) {
UserEntity userEntity = new UserEntity().setName("Waltraud").setLastName("Schmidt").setPassword("TopSecret");
UserDTO dto = (UserDTO) getterToSetter(new UserDTO(), userEntity);
System.out.println(dto.getName()); // prints "Waltraud"
System.out.println(dto.getLastName()); // prints "Schmidt"
}
/**
* Maps all getter of the source to all corresponding setter of the target
* @param target
* target object which should be set
* @param source
* source object to read from
* @return
* returns mapped target object or null if some error occurred
*/
private static Object getterToSetter(Object target, Object source) {
try {
for(Method m: source.getClass().getMethods()){
// try to find for all getters in the source the corresponding setter on the target
if(m.getName().startsWith("get")){
Method setter;
try {
setter = target.getClass().getMethod("set" + m.getName().substring(3), m.getReturnType());
setter.invoke(target,m.invoke(source));
} catch (NoSuchMethodException e) {
//ignored target just haven't a setter for this field
}
}
}
// return value to support builder pattern
return target;
}catch (IllegalAccessException| InvocationTargetException e){
e.printStackTrace();
}
return null;
}
public static class UserEntity {
String password;
String name;
String lastName;
public String getPassword() {
return password;
}
public UserEntity setPassword(String password) {
this.password = password;
return this;
}
public String getName() {
return name;
}
public UserEntity setName(String name) {
this.name = name;
return this;
}
public String getLastName() {
return lastName;
}
public UserEntity setLastName(String lastName) {
this.lastName = lastName;
return this;
}
}
public static class UserDTO {
String name;
String lastName;
public String getName() {
return name;
}
public UserDTO setName(String name) {
this.name = name;
return this;
}
public String getLastName() {
return lastName;
}
public UserDTO setLastName(String lastName) {
this.lastName = lastName;
return this;
}
}
}
这种需求通常最好用 "converter" 或 "mapper" 模式来实现。我在 Java 中生成映射器的首选工具是 MapStruct,但也存在许多其他工具。
使用反射通常不是最佳选择,因为它速度较慢,而且更难以跟踪和自定义(例如,如果字段需要在 JSON 和 [=10= 中的字符串之间转换) ]s 在 Java).
有一个很棒的映射器库,叫做 MapStruct,可以用来映射。
这里是您的 UserEntity 和 UserDTO 的示例:
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping
UserDTO userEntityToUserDTO(UserEntity user);
}
UserDTO userDto = UserMapper.INSTANCE.userEntityToUserDTO(userEntity);
它还支持兼容类型之间的转换,如果字段名称不同,也可以设置自定义映射。例如:
@Mapping(source = "userName", target = "name")
嗨,我有两个 java 对象,它们彼此独立,但共享相同的 getter 和 setter 方法。例如,我有一个 UserEntity 和 UserDTO 对象,我会将所有 getter 值从 UserEntity 映射到所有 setter 的 UserDTO。
做这类事情的最佳方法是什么?我更喜欢用 java 反射来做,但如果外面有一些有用的框架实现,我现在也想这样做。
使用反射不使用外部库
您好,您可以检查源对象的所有 getter,并尝试在目标对象上找到所有相应的 setter。以下方法应该可以做到:
/**
* Maps all getter of the source to all corresponding setter of the target
* @param target
* target object which should be set
* @param source
* source object to read from
* @return
* returns mapped target object or null if some error occurred
*/
private Object getterToSetter(Object target, Object source) {
try {
for(Method m: source.getClass().getMethods()){
// try to find for all getters in the source the corresponding setter on the target
if(m.getName().startsWith("get")){
Method setter;
try {
setter = target.getClass().getMethod("set" + m.getName().substring(3), m.getReturnType());
setter.invoke(target,m.invoke(source));
} catch (NoSuchMethodException e) {
//ignored target just haven't a setter for this field
}
}
}
// return value to support builder pattern
return target;
}catch (IllegalAccessException| InvocationTargetException e){
e.printStackTrace();
}
return null;
}
这是一个完整的Main.class示例,说明它是如何工作的:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author Andreas Hauschild
*/
public class Main {
public static void main(String[] args) {
UserEntity userEntity = new UserEntity().setName("Waltraud").setLastName("Schmidt").setPassword("TopSecret");
UserDTO dto = (UserDTO) getterToSetter(new UserDTO(), userEntity);
System.out.println(dto.getName()); // prints "Waltraud"
System.out.println(dto.getLastName()); // prints "Schmidt"
}
/**
* Maps all getter of the source to all corresponding setter of the target
* @param target
* target object which should be set
* @param source
* source object to read from
* @return
* returns mapped target object or null if some error occurred
*/
private static Object getterToSetter(Object target, Object source) {
try {
for(Method m: source.getClass().getMethods()){
// try to find for all getters in the source the corresponding setter on the target
if(m.getName().startsWith("get")){
Method setter;
try {
setter = target.getClass().getMethod("set" + m.getName().substring(3), m.getReturnType());
setter.invoke(target,m.invoke(source));
} catch (NoSuchMethodException e) {
//ignored target just haven't a setter for this field
}
}
}
// return value to support builder pattern
return target;
}catch (IllegalAccessException| InvocationTargetException e){
e.printStackTrace();
}
return null;
}
public static class UserEntity {
String password;
String name;
String lastName;
public String getPassword() {
return password;
}
public UserEntity setPassword(String password) {
this.password = password;
return this;
}
public String getName() {
return name;
}
public UserEntity setName(String name) {
this.name = name;
return this;
}
public String getLastName() {
return lastName;
}
public UserEntity setLastName(String lastName) {
this.lastName = lastName;
return this;
}
}
public static class UserDTO {
String name;
String lastName;
public String getName() {
return name;
}
public UserDTO setName(String name) {
this.name = name;
return this;
}
public String getLastName() {
return lastName;
}
public UserDTO setLastName(String lastName) {
this.lastName = lastName;
return this;
}
}
}
这种需求通常最好用 "converter" 或 "mapper" 模式来实现。我在 Java 中生成映射器的首选工具是 MapStruct,但也存在许多其他工具。
使用反射通常不是最佳选择,因为它速度较慢,而且更难以跟踪和自定义(例如,如果字段需要在 JSON 和 [=10= 中的字符串之间转换) ]s 在 Java).
有一个很棒的映射器库,叫做 MapStruct,可以用来映射。
这里是您的 UserEntity 和 UserDTO 的示例:
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping
UserDTO userEntityToUserDTO(UserEntity user);
}
UserDTO userDto = UserMapper.INSTANCE.userEntityToUserDTO(userEntity);
它还支持兼容类型之间的转换,如果字段名称不同,也可以设置自定义映射。例如:
@Mapping(source = "userName", target = "name")