Java 在Hibernate中自动应用字段转换功能

Java 在Hibernate中自动应用字段转换功能,java,database,hibernate,encryption,jpa,Java,Database,Hibernate,Encryption,Jpa,我有一个数据库表,其中有一个字段需要通过Hibernate进行读写。它是字符串字段,但内容是加密的。出于各种原因(例如,需要对纯文本值进行排序),加密/解密函数在数据库内部实现,而不是在Java中实现 我现在正在努力解决的问题是找到一种方法,在引用字段的任何地方调用Hibernate生成的SQL中的加密/解密函数,并且这种方法对我的应用程序代码是透明的。这可能吗?我研究了Hibernate对“派生”属性的支持,但不幸的是,这种方法不支持读写字段。任何想法都值得赞赏。假设您可以从Java中访问加密

我有一个数据库表,其中有一个字段需要通过Hibernate进行读写。它是字符串字段,但内容是加密的。出于各种原因(例如,需要对纯文本值进行排序),加密/解密函数在数据库内部实现,而不是在Java中实现


我现在正在努力解决的问题是找到一种方法,在引用字段的任何地方调用Hibernate生成的SQL中的加密/解密函数,并且这种方法对我的应用程序代码是透明的。这可能吗?我研究了Hibernate对“派生”属性的支持,但不幸的是,这种方法不支持读写字段。任何想法都值得赞赏。

假设您可以从Java中访问加密/解密算法,我将设置我的映射类

public class encryptedTable {
    @Column(name="encrypted_field")
    private String encryptedValue;

    @Transient
    private String value;

    public String getEncryptedValue() {
        return encryptedValue;
    }

    public String getValue() {
        return value;
    }

    public void setEncryptedValue(String encryptedValue) {
        this.encryptedValue = encryptedValue;
        this.value = decrypt(encryptedValue);
    }

    public void setValue(String value) {
        this.value = value;
        this.encryptedValue = encrypt(value);
    }
}

然后使用get/set Value作为程序中的访问器,并将get/set EncryptedValue留给Hibernates在访问数据库时使用。

数据库内部可能有一个触发器,在检索时,解密值并替换返回的结果,插入时加密值并用加密值替换存储的结果。您也可以使用视图包装器来实现这一点,即在视图上有一个insert触发器,并让视图自动解密该值


为了更好地解释:有一个对值进行解密的视图,以及一个对链接到该视图的值进行加密的插入触发器。

我认为没有办法使加密像您描述的那样对应用程序完全透明。您可以得到的最接近的方法是使其在实体外部透明。在实体类中:

@Entity
@SQLInsert(sql="INSERT INTO my_table(my_column, id) VALUES(encrypt(?),?)")
@SQLUpdate( sql="UPDATE my_table SET my_column = encrypt(?) WHERE id = ?")
public class MyEntity {

  private String myValue;

  ....

  @Formula("decrypt(my_column)")
  public String getValue() {
    return myValue;
  }

  public void setValue(String value) {
    myValue = value;
  }

  @Column (name="my_column")
  private String getValueCopy() {
    return myValue;
  }

  private void setValueCopy(String value) {
  }

}
映射为派生属性,您应该能够在查询中使用它。
valueCopy
是私有的,用于绕过只读的派生属性。

SQLInsert
SQLUpdate
是一种黑色巫毒魔法,可以在插入/更新时强制加密。请注意,参数顺序非常重要,您需要了解Hibernate在不使用自定义插入/更新的情况下生成参数的顺序,然后进行复制。

为什么不通过调用Hibernate中的存储过程来使用SQl server加密,而不是让Hibernate生成查询呢?

实际上,最终,我走了另一条路,提交了一份冬眠报告。它是上周发布到trunk的,所以我认为它将在3.5之后的下一个版本中发布。现在,在属性映射中,您可以指定SQL“读”和“写”表达式来调用SQL函数或执行其他类型的数据库端转换。

这并不能满足我在查询中引用字段(例如用于排序)时让Hibernate自动调用数据库解密函数的愿望.你能澄清一下对纯文本进行排序的
位吗?这是否意味着您正在执行类似于从my_表中按解密顺序选择my_字段(my_字段)
的操作?是的,但更像是从my_表中按解密顺序选择解密(my_字段)。这就是一个例子。我还需要使用LIKE操作符进行不区分大小写的搜索(对解密值调用UPPER)和部分字符串匹配。所有这些都要求数据库能够进行解密。我曾考虑过这样的事情,但认为维护起来太难,因为我有几个带有加密字段的表,并且我依赖Hibernate自动生成模式。但也许有一种方法可以动态生成视图和触发器。嗯……我们使用了类似的方法,但是我们已经生成了数据库,然后我们对它进行了反向工程。如果要从对象安装数据库,则可以将视图/触发器的架构作为单独的一部分进行安装,然后将其作为安装脚本/执行的一部分进行安装。当插入、更新或删除数据时,将调用数据库触发器,而不是选择数据。您不会使用触发器,而是使用视图来处理选择,以及插入到视图中的触发器,即视图将处理选择逻辑,触发器将处理插入逻辑。如果不清楚的话,很抱歉。我正在寻找一个视图包装器和用于插入和更新的触发器的组合。这实现了我所期望的透明度。谢谢。存储过程不能解决在查询中引用字段时自动解密字段的问题。我们做了这样的概念验证。我对“假”属性不感兴趣,但我喜欢将显式插入和更新与视图结合使用的想法。谢谢