2011-09-28 57 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

相关问题