java:我可以通过观察hashcode来观察对象的值变化吗?

时间:2011-09-28 09:46:54

标签: java

我有一个Model类 DOModel

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 ,我使用所有属性的哈希码的组合来测量模型是否被更改。基本流程是:

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新手,我担心有潜在的问题。所以在我走得更远之前,我想证明我的方式不会把我带到错误的地方。

作为一名中国人,我的英语不够好。如果你有问题要理解我在说什么,请发表评论,我会尽力编辑这个问题。

非常感谢!

5 个答案:

答案 0 :(得分:1)

这听起来像是依赖于“相等的哈希码意味着相等的对象”, 可以安全依赖。

假设hashCode的正确实现,您应该能够依赖“不同的哈希码表示不相等的对象” - 但反之则为真。

特别是:

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

总是有效。 Sucky,但有效。

答案 1 :(得分:1)

如果要确保没有更改,则必须比较属性的内容而不是哈希码。为此,您应该实现equals方法。哈希码的问题在于,虽然不太可能,但对于不同的属性值,它可能是相同的值。

答案 2 :(得分:1)

这种方法可能存在一些问题:两个不同的对象可能具有相同的hashCode值(哈希码的合约只有在a.equals(b)为真时才有,然后a.hashCode == b.hashCode,理论上,所有hashCodes都可以返回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);

答案 3 :(得分:0)

这不是覆盖hashCode()的方式。 Joshua Bloch告诉你在他的“Effective Java”的chapter 3中做正确的方法。

答案 4 :(得分:0)

  

它似乎现在正常运作,但作为Java新手,我担心会有潜在的问题。

这不是一种安全的方法:对象的更改,保证对象哈希代码更改。

请记住,哈希码只是int。如果您的对象具有超过2个 32 状态(如您的情况),则您将遇到哈希冲突。


关于您的代码的更多指示:

  • 覆盖hashCode时,您还需要覆盖equals
  • 您的hashCode实施不是很好(它没有提供非常好的发布)