有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一个模型班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实例对象相对于一个特定的时间被修改了

请注意方法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新手,我担心存在潜在的问题。所以在我继续之前,我想证明我的方式不会把我带到错误的地方

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

非常感谢


共 (2) 个答案

  1. # 1 楼答案

    It seems that works right now, but as a Java newbie, I am worrying there is potential problems.

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

    请记住,哈希代码只是一个int。如果你的对象有超过2个32个状态(就像你的例子一样),你肯定会有哈希冲突


    关于您的代码,还有几点建议:

    • 重写hashCode时,还需要重写equals
    • 您的hashCode实现不是很好(它没有提供很好的分发)
  2. # 2 楼答案

    这种方法可能存在一些问题:两个不同的对象可能具有相同的hashCode值(hashCode的约定是,如果a.equals(b)为真,那么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);