Reputation: 18639
I have few Pojos in different packages, each POJO contains set of the another pojo from the same package. I need to copy all items with the same name from Package B Pojos to objects in Package A.
Eaxmple:
package com.vanilla.packageA;
public class Student{
private String firstName;
private String lastName;
private Set<Course> course;
//getters and setters ommited
}
package com.vanilla.packageA;
public class Course{
private String courseName;
private String courseDescription;
//seters and getters
}
package com.vanilla.packageB;
public class Student{
private String firstName;
private String lastName;
private Address address;
private Set<Course> course;
Private Date birtday;
//getters and setters ommited
}
package com.vanilla.packageB;
public class Course{
private String courseName;
private String courseDescription;
private <Lecturer> lecturer;
private Integer hours;
//seters and getters
}
I want to copy recursively all items from PackageB
classes to packageA
classes which exists in PaCkageB
and shares the same name.
Updates:
Guys, I understand that that this is stupid question, but I need to maintain this code, now the code is written in the way that they have to call 50 getters and setter, or calling constructor with 50 parameters. Unfortunately, I can't use the same object and I need to copy it, but I must find more "elegant" way to copy tese beans.
Upvotes: 15
Views: 21690
Reputation: 10763
Try jodd library.
Dependency:
<dependency>
<groupId>org.jodd</groupId>
<artifactId>jodd-bean</artifactId>
<version>5.1.6</version>
</dependency>
Code example:
MyObject source = ...
MyObject target = ...
BeanCopy.beans(source, target).declared(true, true).copy();
Upvotes: 0
Reputation: 11
have you tried using BULL? you can find a guide on how to use it on DZone. It offers the possibility to also perform object transformation while coping. Moreover, it performs the copy recursively and don't need getter and setters defined.
Upvotes: 1
Reputation: 13835
Using PropertyUtils, you can copy onky the non null properties as follows:
private void copyNonNullProperties(Object destination,
Object source) {
try {
PropertyUtils.describe(source).entrySet().stream()
.filter(source -> source.getValue() != null)
.filter(source -> !source.getKey().equals("class"))
.forEach(source -> {
try {
PropertyUtils.setProperty(destination, source.getKey(), source.getValue());
} catch (Exception e22) {
log.error("Error setting properties : {}", e22.getMessage());
}
});
} catch (Exception e1) {
log.error("Error setting properties : {}", e1.getMessage());
}
}
Upvotes: 0
Reputation: 6075
If you already have spring dependencies you could use org.springframework.beans.BeanUtils
BeanUtils.copyProperties(from, to);
Upvotes: 3
Reputation: 25956
Any reason why Apache BeanUtils.copyProperties does not work?
Upvotes: 19
Reputation: 365
Copying fields values are a need I almost every project, for example for do the clone(). I also think that for accomplish some goals isn't necessary import .jars for using only one function. I would like share some little code in which I was working, there are some things that I left in the inkwell but in general it do the work. In this case I use reflection.
public class ObjectCopyTools {
static String[] bases = new String[] {"byte", "short", "int", "long", "float", "double", "char", "boolean"};
static String[] equivalents = new String[] {"Byte", "Short", "Integer", "Long", "Float", "Double", "Character", "Boolean"};
static {
}
private static boolean areEquivalents(String type1, String type2){
for (int i = 0; i < bases.length; i++) {
if((type1.equals(bases[i]) && type2.equals(equivalents[i]))
|| (type2.equals(bases[i]) && type1.equals(equivalents[i]))){
return true;
}
}
return false;
}
public static <T extends Object, Y extends Object> Y deepReflectionObjectCopy(T origin, Class<Y> resultClass) {
Class<? extends Object> origClass = origin.getClass();
Y resultObject = null;
for (Constructor<?> constructor : resultClass.getConstructors()) {
if (constructor.getParameterCount() == 0) {
try {
resultObject = (Y) constructor.newInstance();
}catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
}
break;
}
}
if(resultObject == null){
return null;
}
Field[] origFields = origClass.getDeclaredFields();
Field[] destFields = resultObject.getClass().getDeclaredFields();
Object value = null;
for(Field dstField: destFields){
try {
Field tempOrigField = origClass.getDeclaredField(dstField.getName());
if(tempOrigField.getType().equals(dstField.getType())
|| areEquivalents(tempOrigField.getType().getSimpleName(), dstField.getType().getSimpleName())){
dstField.set(resultObject, tempOrigField.get(origin));
}
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
}
}
return resultObject;
}
Hope this help.
Upvotes: 1
Reputation: 5614
See to mapstruct. This tools generates code, so there is no overhead on reflection.
Upvotes: 5
Reputation: 154
Well.. Dozer may be just the thing you're looking for.
. . . its an object to object mapping framework. The idea is that:
. . therefore mapping files are as compact as possible. Its useful for many cases, such as mapping a use-case specify service payload on to the reusable core model objects.
When delivering the SpringSource training courses we used to point out this framework very often.
Upvotes: 6
Reputation: 308733
If DRY is a bedrock principle of computer science, what reason can you give for two identical, parallel object graphs? Not only have you doubled your maintenance burden, but now you have to develop a recursive method to do nothing but ferry data from one to the other.
Upvotes: 0