2011-09-28 22 views
0

我有一個模型類DOModeljava:我可以通過觀察哈希碼來觀察對象上的值更改嗎?

package amarsoft.dbmp.credit.web.model; 

import ejp.annotations.ConcreteTableInheritance; 
import amarsoft.rcp.base.databinding.BindableModel; 

@ConcreteTableInheritance 
public class DOModel extends BindableModel { 
    /** 
    * 編號 
    */ 
    private String id; 
    /** 
    * 名稱 
    */ 
    private String name; 
    /** 
    * 模板類型,沒有太大意義 
    */ 
    private String type; 
    /** 
    * 模板參數 
    */ 
    private String args; 

    private String updateTable; 

    private String updateWhere; 

    private String fromClause; 

    private String whereClause; 

    private String groupClause; 

    private String orderClause; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.firePropertyChange("id", this.id, this.id = id); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.firePropertyChange("name", this.name, this.name = name); 
    } 

    public String getType() { 
     return type; 
    } 

    public void setType(String type) { 
     this.firePropertyChange("type", this.type, this.type = type); 
    } 

    public String getArgs() { 
     return args; 
    } 

    public void setArgs(String args) { 
     this.firePropertyChange("args", this.args, this.args = args); 
    } 

    public String getUpdateTable() { 
     return updateTable; 
    } 

    public void setUpdateTable(String updateTable) { 
     this.firePropertyChange("updateTable", this.updateTable, this.updateTable = updateTable); 
    } 

    public String getDoUpdateWhere() { 
     return updateWhere; 
    } 

    public void setDoUpdateWhere(String doUpdateWhere) { 
     this.firePropertyChange("updateWhere", this.updateWhere, this.updateWhere = doUpdateWhere); 
    } 

    public String getFromClause() { 
     return fromClause; 
    } 

    public void setFromClause(String fromClause) { 
     this.firePropertyChange("fromClause", this.fromClause, this.fromClause = fromClause); 
    } 

    public String getWhereClause() { 
     return whereClause; 
    } 

    public void setWhereClause(String whereClause) { 
     this.firePropertyChange("whereClause", this.whereClause, this.whereClause = whereClause); 
    } 

    public String getGroupClause() { 
     return groupClause; 
    } 

    public void setGroupClause(String groupClause) { 
     this.firePropertyChange("groupClause", this.groupClause, this.groupClause = groupClause); 
    } 

    public String getOrderClause() { 
     return orderClause; 
    } 

    public void setOrderClause(String orderClause) { 
     this.firePropertyChange("orderClause", this.orderClause, this.orderClause = orderClause); 
    } 

    @Override 
    public String toString() { 
     return "DOModel [id=" + id + ", name=" + name + "]"; 
    } 

    @Override 
    public int dataValueHashCode() { 
     int code = 0; 
     if (id != null) { 
      code += id.hashCode(); 
     } 
     if(name != null){ 
      code += name.hashCode(); 
     } 
     if(type != null){ 
      code += type.hashCode(); 
     } 
     if(args != null){ 
      code += args.hashCode(); 
     } 
     if(updateTable != null){ 
      code += updateTable.hashCode(); 
     } 
     if(updateWhere != null){ 
      code += updateWhere.hashCode(); 
     } 
     if(fromClause != null){ 
      code += fromClause.hashCode(); 
     } 
     if(whereClause != null){ 
      code += whereClause.hashCode(); 
     } 
     if(groupClause != null){ 
      code += groupClause.hashCode(); 
     } 
     if(orderClause != null){ 
      code += orderClause.hashCode(); 
     } 
     return code; 
    } 

} 

這個類是在ORM使用,當DOModel的實例的一個或多個屬性發生變化,我需要堅持的DOModel的實例回數據庫。

所以對我來說存在一個問題:我怎麼能知道一個DOModel實例對象與特定時間相比被修改了?

請注意方法dataValueHashCode,我使用所有屬性的哈希碼的組合來衡量,如果一個模型是changed.the基本流程是:

1.load the a DOModel object from database 
2.call dataValueHashCode method and cache it 
3.(optional)modify property values 
4.when need to save the object back to database, call dataValueHashCode method again 
and compare it to the cached one 
5.if match, no change. if not match, save it back to database. 

看來,現在的工作原理,但作爲一個java新手,我擔心有潛在的問題。所以在我走之前,我想證明我的方式不會導致我錯誤的地方。

作爲中國人,我的英語不夠好。如果你有問題要了解我在說什麼,請發表評論,我會盡我所能編輯此問題。

非常感謝!

回答

1

該方法可能存在某些錯誤:兩個不同的對象可能具有相同的hashCode值(hashcode的約定僅當a.equals(b)爲true時,則a.hashCode == b.hashCode,從理論上講,所有的hashCode可能會返回1,他們仍然有效,儘管效率低下)

所以你需要想出一個你的密碼散列不使用散列碼,如果你想絕對肯定它反映了你的對象改變。我建議使用MD5加密,它(幾乎)唯一標識一個字符串。它不完全抵抗碰撞(理論上講,有多個輸出相同的字符串),但實際上它已經足夠好了。

http://en.wikipedia.org/wiki/MD5

這是很容易在Java中做到:

final MessageDigest messageDigest = MessageDigest.getInstance("MD5"); 
final byte[] data = stringToConvert.getBytes(); 
messageDigest.update(data,0,data.length); 
final BigInteger hash = new BigInteger(1,messageDigest.digest()); 
return String.format("%1$032X", hash); 
+0

非常感謝你! – CaiNiaoCoder

0

這不是覆蓋hashCode()的方法。 Joshua Bloch告訴你他的「Effective Java」的chapter 3正確的方法。

0

看來現在工作,但作爲一個Java新手,我擔心有潛在的問題。

這不是一個安全的方法:在一個對象的變化,確實保證的對象哈希碼的改變。

請記住,散列碼僅僅是一個int。如果你的對象有超過2個狀態(和你的情況一樣),你肯定會有散列衝突。


一些更多的關於您的代碼指針:

  • 當重寫hashCode,您還需要重寫equals
  • hashCode執行不太好(但它不提供一個很好的分佈)
1

這聽起來像你依靠「平等的哈希碼暗示相等的對象」,這是安全依靠。

假設正確執行hashCode,您應該可以依靠「不同的哈希碼錶示不等的對象」 - 但相反是而不是爲真。

尤其的實現:

@Override public int hashCode() { 
    return 0; 
} 

總是有效。 Sucky,但是有效的。

+0

可以String類的hashCdoe實施保障 「不平等串意味着不平等的散列碼」?正如你所看到的,我的DOModel類只包含字符串屬性 – CaiNiaoCoder

+0

@YAMaiDie:絕對不是。考慮有多少可能的哈希碼(假設'hashCode()'返回一個'int') - 現在想想可能有多少不同的字符串......並且即使它對一個*單個字符串有效, 'd需要考慮你是如何*合併*哈希代碼... –

1

如果你想確定沒有變化,你必須比較屬性的內容而不是哈希碼。爲此,您應該實施equals方法。散列碼的問題是,雖然不太可能對不同的屬性值是相同的值。

+0

謝謝@Gandalf如果我實現「等於」方法,我需要緩存一個對象的副本以供比較。不是嗎? – CaiNiaoCoder

+0

不,等於你比較當前對象和給定的參數。但是在你開始工作之前:如果你正在使用Eclipse,有一個函數Source-> Generate hasCode,並且等於那個con爲你做。 – Gandalf