2011-09-19 86 views
4

我使用spring MVC從客戶端接收JSON並自動創建一個對象。問題是客戶端不會將實體中的所有字段發送給服務器,但某些字段爲空並覆蓋調用userDao.persist(user)的現有值。例如,我有這個實體:如何避免使用空值覆蓋非空值?

@Entity 
public class User { 

    @Id @GeneratedValue 
    private int id; 

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

,但用戶從來不給我密碼,所以從內置JSON對象具有「密碼」字段爲空。我不希望密碼字段被空值覆蓋。有一種方法可以說休眠「如果你發現一個空值忽略它,不覆蓋保存在數據庫中的值?」。我無法相信這個顯然很簡單的問題並不容易解決。

+0

使用@jsoningnore註解密碼字段 –

回答

-1

如果你的問題只是數據庫,那麼我建議你使用一個存儲過程,它檢查該值是否爲空,然後不改變現有值。這樣你仍然可以發送一個空值,並且你的驗證在服務器端更加健壯。

+1

你的意思是: public void update(User jsonUser){ User dbUser = userDao.getUserById(jsonUser。getIdApp());如果(jsonUser.getName()!= null) dbUser.setName()= jsonUser.getName(); } – Fabio

+0

對不起以前的評論,我不知道如何在評論中使用縮進:-D – Fabio

+0

我認爲註釋中的縮進是不可能的。無論如何讀[this](http://www.mysqltutorial.org/mysql-stored-procedure-tutorial.aspx)。它是一個關於存儲過程的教程。一般來說,它就像由數據庫執行的一個小函數,所以你可以100%確定你所有的數據都在那裏被檢查過。無論你最初使用什麼語言,只需調用該程序,而不是調用'insert into ....' –

0

爲您設置setter屬性並在那裏執行檢查。

6

我認爲你的問題的根源是你從JSON解析中得到的對象從來沒有實際的值。這是一個只有JSON中設置的值的bean。

您需要從DB加載實體,然後將JSON中的非空字段設置到加載的實體上。這樣,只有在JSON中提供的字段纔會被設置。

在保存數據庫版本之前,我推薦使用某種適配器來「合併」(不是JPA合併)數據庫版本和JSON版本。

添加@NotNull約束和Bean驗證將確保嘗試保存時值不爲空。不幸的是,他們不會幫助您將值存入實體以保存。

+0

是的,你關注的問題。關鍵是我需要知道這是什麼「適合某種合併適配器」。因爲另一種方式是(就像你說的那樣)「將JSON中的非空字段設置到加載的實體上」,這可能非常枯燥和不雅,需要在具有20個字段的實體上手動完成。 – Fabio

+0

@Fabio不幸的是,我們有時必須做無聊的事情。這個想法是做一次!我建議創建一個單獨的對象(也是接口)來執行合併,這樣您可以封裝合併邏輯。然後,您可以在需要的地方進行測試和重用。 –

+0

我該如何做一次?對於每個實體,合併的實施必須不同...... – Fabio

2

我有同樣的問題。 我解決了它在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; 
} 
} 

這顯然是一種解決方法,但它似乎工作順利......在接下來的幾天裏,我想我會寫遞歸部分。

+0

請在您的答案本身中包含代碼。 – Unihedron