代码之家  ›  专栏  ›  技术社区  ›  Rob H

在休眠中自动应用字段转换功能

  •  2
  • Rob H  · 技术社区  · 15 年前

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

    我现在正在努力解决的问题是找到一种方法来调用Hibernate生成的SQL中的加密/解密函数,无论该字段在何处被引用,并且以对我的应用程序代码透明的方式。这有可能吗?我研究过Hibernate对“派生”属性的支持,但不幸的是,这种方法不支持读写字段。有什么好主意吗?

    5 回复  |  直到 9 年前
        1
  •  4
  •   ChssPly76    15 年前

    我认为没有办法像你描述的那样进行加密 完全地 对应用程序透明。你能得到的最接近的东西是使它在实体外部透明。在实体类中:

    @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) {
      }
    
    }
    

    value 映射为派生属性,您应该能够在查询中使用它。
    valueCopy 是私有的,用于绕过只读的派生属性。
    SQLInsert SQLUpdate 是黑色巫毒魔法,在插入/更新时强制加密。注意参数顺序 重要的是,您需要了解Hibernate在不使用自定义插入/更新的情况下生成参数的顺序,然后复制它。

        2
  •  1
  •   aperkins    15 年前

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

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

        3
  •  1
  •   Rob H    15 年前

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

        4
  •  -1
  •   Mike Clark    15 年前

    假设您可以从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值用作程序中的访问器,并将get/set encryptedvalue保留为访问数据库时休眠使用的值。

        5
  •  -1
  •   HLGEM    15 年前

    为什么不使用似乎已经存在的SQL Server加密,方法是在Hibernate中调用存储过程,而不是让Hibernate生成查询?