【问题标题】:Can Hibernate automatically uppercase a column on read/insert via configuration?Hibernate 可以通过配置自动大写读取/插入的列吗?
【发布时间】:2011-01-25 03:31:01
【问题描述】:

我们有一些列的数据必须始终为大写以确保唯一性。我想知道 hibernate 是否可以通过一些配置文件更改强制所有这些列为大写?

我们实际上使用自定义 UserType 来加密/解密其他表的列数据,但我认为将所有内容都大写会过度...

另外,我正在考虑修改模型,以便所有 getter/setter 将大写任何来来往往的字符串。

最坏的(?)情况是修改 Oracle 列约束以在检查唯一性时忽略大小写。

有什么想法吗?

【问题讨论】:

    标签: oracle hibernate orm


    【解决方案1】:

    我不知道有任何配置设置可以实现这一点。但是,您可以尝试使用 interceptor 在插入/更新时修复数据,例如:

    package interceptor;
    
    import java.io.Serializable;
    
    import org.hibernate.EmptyInterceptor;
    import org.hibernate.type.Type;
    
    public class CustomSaveInterceptor extends EmptyInterceptor {
        public boolean onSave(Object entity,
            Serializable id,
            Object[] state,
            String[] propertyNames,
            Type[] types)
        {
            if (entity instanceof MyClass) {
                MyClass myInstance = (MyClass)entity;
                myInstance.setName(myInstance.getName().toUpperCase());
            }
            return super.onSave(entity, id, state, propertyNames, types);
        }
    }
    

    【讨论】:

    • 我有一个拦截器,其中包含其他“东西”,我可以将你的想法放入其中......但我没有看到为十几个需要它们的类编写一堆 if 逻辑字段为大写。
    【解决方案2】:

    我建议查看此页面:http://forum.springsource.org/archive/index.php/t-18214.html

    它有 3 种不同的方法来做到这一点。我相信侵入性最小的方式是这样的:

    <property name="upperCaseName" formula="upper(name)" lazy="true"/>
    

    【讨论】:

    • 我可能是错的,但我认为公式技巧不适用于插入或更新(我认为 Hibernate 将公式字段视为瞬态并且不将它们保存在数据库中)。
    【解决方案3】:

    几种解决方案:

    1. 使用数据库触发器(虽然不是通过配置)。
    2. 修改 getter/setter(虽然不是通过配置)。
    3. 使用UserType 将属性转换为大写。
    4. 使用interceptorevent listener

    解决方案 #1 对代码是透明的,但我不是“背后”触发器的忠实拥护者,而且我不喜欢到处传播业务规则。解决方案 #3 和 #4 依赖于 Hibernate(但这可能不是问题)。如果您可以更改代码,解决方案 #2 是最简单和最便携的解决方案。如果这是一个选项,那将是我的选择。

    【讨论】:

    • 我也倾向于#2,但我正在寻找一种“正常工作”的休眠配置......
    • @T Reddy 开箱即用的 AFAIK 没有类似的东西。
    【解决方案4】:

    我决定实现一个 UserType...它尽可能接近休眠配置...这是代码...

    package model;
    
    import java.io.Serializable;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;
    
    import org.apache.commons.lang.builder.EqualsBuilder;
    import org.apache.commons.lang.builder.HashCodeBuilder;
    import org.hibernate.Hibernate;
    import org.hibernate.HibernateException;
    import org.hibernate.usertype.UserType;
    
    public class UpperCaseUserType implements UserType {
        private static final int[] TYPES = {Types.VARCHAR};
    
    public int[] sqlTypes() {
            return TYPES;
    }
    
    public Class returnedClass() {
            return String.class;
    }
    
    public boolean equals(Object x, Object y) throws HibernateException {
            if (x == y) {
                return true;
            }
            if (null == x || null == y) {
                return false;
            }
            return new EqualsBuilder().append(x, y).isEquals();
    }
    
    public int hashCode(Object o) throws HibernateException {
            return new HashCodeBuilder().append(o).toHashCode();
    }
    
    public Object nullSafeGet(ResultSet resultSet, String[] strings, Object object) throws HibernateException, SQLException {
            return ((String) Hibernate.STRING.nullSafeGet(resultSet, strings[0])).toUpperCase();
    }
    
    public void nullSafeSet(PreparedStatement preparedStatement, Object object, int i) throws HibernateException, SQLException {
            String string = ((String) object).toUpperCase();
            Hibernate.STRING.nullSafeSet(preparedStatement, string, i);
    }
    
    public Object deepCopy(Object o) throws HibernateException {
            if (null == o) {
                return null;
            }
            return new String(o.toString());
    }
    
    public boolean isMutable() {
            return false;
    }
    
    public Serializable disassemble(Object o) throws HibernateException {
            return (String) o;
    }
    
    public Object assemble(Serializable serializable, Object o) throws HibernateException {
            return serializable;
    }
    
    public Object replace(Object o, Object arg1, Object arg2) throws HibernateException {
            return o;
    }
    }
    

    考虑这个属性元素

    <property name="serialNumber" type="model.UpperCaseUserType">
        <column name="SERIAL_NUMBER" length="20" not-null="true" unique="true" />
    </property>
    

    所以推理......当hibernate插入数据时,这种类型会将字符串转换为大写。当休眠选择数据时,会发生同样的事情。与仅将 bean 的 get/set 更改为大写所有内容相比,此类的优势是当我使用 Criteria 来选择 serialNumber 时。 Hibernate 也会将我的参数大写,因为它将转换/应用与表配置中定义的相同类型。

    因此,我不需要记住手动将我所有的序列号搜索条件大写...hibernate 会为我处理这些...这正是我想要在这里实现的目标!

    我有一个 JUnit 可以演示所有这些东西,但我认为我的答案太大了......

    【讨论】:

      【解决方案5】:

      更简洁的方法:

      @Column(name = "DUMMY")
      @ColumnTransformer(read = "UPPER(DUMMY)")
      private String dummy
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多