Fabio
Fabio

Reputation: 652

How to avoid overwriting of non-null values with null values?

I'm using spring MVC for receiving a JSON from client and automatically create an object from it. The problem is that the client doesn't send to server all the fields that are in the entity, but some fields are null and overwrite existing values calling userDao.persist(user). For example, i have this entity:

@Entity
public class User {

    @Id @GeneratedValue
    private int id;

    private String username;
    private String password;
    private String email;

But the user never send me the password, so the object built from JSON has "password" field empty. I don't want the password field to be overwritten by a null value. There's a way to say to hibernate "if you find a null value ignore it and don't overwrite the value that is saved in database?". I can't believe that there isn't a easy solution to this apparently simple problem.

Upvotes: 6

Views: 10634

Answers (5)

Ramzi Khahil
Ramzi Khahil

Reputation: 5052

I wrote this answer while being an unexpirienced studen. Today my answer would be similar to the one from @James DW. Also, from the term userDao, I assume that it is some kind of ORM/ODM. In that case it is definitly worth searching "pros and cons of ORM/ODM".

original answer (which was accepted back in 2011):

If your problem is only the database, then I suggest you use a stored procedure, which checks if that value is null, and then dose not change the existing value. That way you can still send a null value, and your validation is on server side which is more robust.

Upvotes: -3

Paolinux
Paolinux

Reputation: 177

I have the same issue. I solved it in this way.

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import java.lang.reflect.Field;
import java.util.Hashtable;



public class Updater {

private final static Logger log = LogManager.getLogger(Updater.class);

public static <E> E updater(E oldEntity, E newEntity) {

    Field[] newEntityFields = newEntity.getClass().getDeclaredFields();
    Hashtable newHT = fieldsToHT(newEntityFields, newEntity);

    Class oldEntityClass = oldEntity.getClass();
    Field[] oldEntityFields = oldEntityClass.getDeclaredFields();

    for (Field field : oldEntityFields){
        field.setAccessible(true);
        Object o = newHT.get(field.getName());
        if (o != null){
            try {
                Field f = oldEntityClass.getDeclaredField(field.getName());
                f.setAccessible(true);
                log.info("setting " + f.getName());
                f.set(oldEntity, o);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }

        }

    return oldEntity;
    }



private static Hashtable<String, Object> fieldsToHT(Field[] fields, Object obj){
    Hashtable<String,Object> hashtable = new Hashtable<>();
    for (Field field: fields){
        field.setAccessible(true);
        try {
            Object retrievedObject = field.get(obj);
            if (retrievedObject != null){
                log.info("scanning " + field.getName());
                hashtable.put(field.getName(), field.get(obj));
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    return hashtable;
}
}

It is clearly a workaround but it seems to work smoothly... in the next days I think I'll write the recursive part.

Upvotes: 2

James DW
James DW

Reputation: 1815

I think the source of your problem is that the object you're getting back from your JSON parsing never had the actual values in it. It is a bean that has only the values set that are in your JSON.

You need to load your entity from the DB and then set the non-null fields from your JSON onto the loaded entity. That way only fields that are supplied in the JSON will be set.

I recommend an adapter of some sort to "merge" (not JPA merge) the DB version and the JSON version before saving the DB version.

Adding a @NotNull constraint and Bean Validation will make sure the values are not null when attempting to save. Unfortunately they won't help you get the values into the entity to save.

Upvotes: 6

dma_k
dma_k

Reputation: 10639

Check Hibernate Validation project, which can be used to verify your object on DAO level, as well as on Spring Web layer.

Upvotes: 0

SJuan76
SJuan76

Reputation: 24780

Implement setters for you attributes and do the checks there.

Upvotes: 0

Related Questions