Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to compare several javabean properties?

I need to compare dozens of fields in two objects (instances of the same class), and do some logging and updating in case there are differences. Meta code could look something like this:

if (a.getfield1 != b.getfield1)
  log(a.getfield1 is different than b.getfield1)
  b.field1 = a.field1

if (a.getfield2!= b.getfield2)
  log(a.getfield2 is different than b.getfield2)
  b.field2 = a.field2

...

if (a.getfieldn!= b.getfieldn)
  log(a.getfieldn is different than b.getfieldn)
  b.fieldn = a.fieldn

The code with all the comparisons is very terse, and I would like to somehow make it more compact. It would be nice if I could have a method which would take as a parameter method calls to setter and getter, and call this for all fields, but unfortunately this is not possible with java.

I have come up with three options, each which their own drawbacks.

1. Use reflection API to find out getters and setters
Ugly and could cause run time errors in case names of fields change

2. Change fields to public and manipulate them directly without using getters and setters
Ugly as well and would expose implementation of the class to external world

3. Have the containing class (entity) do the comparison, update changed fields and return log message
Entity should not take part in business logic

All fields are String type, and I can modify code of the class owning the fields if required.

EDIT: There are some fields in the class which must not be compared.

like image 204
tputkonen Avatar asked May 15 '09 07:05

tputkonen


1 Answers

Use Annotations.

If you mark the fields that you need to compare (no matter if they are private, you still don't lose the encapsulation, and then get those fields and compare them. It could be as follows:

In the Class that need to be compared:

@ComparableField 
private String field1;

@ComparableField
private String field2;

private String field_nocomparable;

And in the external class:

public <T> void compare(T t, T t2) throws IllegalArgumentException,
                                          IllegalAccessException {
    Field[] fields = t.getClass().getDeclaredFields();
    if (fields != null) {
        for (Field field : fields) {
            if (field.isAnnotationPresent(ComparableField.class)) {
                field.setAccessible(true);
                if ( (field.get(t)).equals(field.get(t2)) )
                    System.out.println("equals");
                field.setAccessible(false);
            }
        }
    }
}

The code is not tested, but let me know if helps.

like image 124
David Santamaria Avatar answered Sep 22 '22 04:09

David Santamaria