Hibernate可以通过配置在读取/插入时自动大写一列吗?

时间:2010-03-08 19:57:48

标签: oracle hibernate orm

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

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

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

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

有什么想法吗?

5 个答案:

答案 0 :(得分:6)

更清洁的方法:

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

答案 1 :(得分:3)

几种解决方案:

  1. 使用数据库触发器(但不是通过配置)。
  2. 修改getter / setter(不过通过配置)。
  3. 使用UserType将属性转换为大写。
  4. 使用interceptorevent listener
  5. 解决方案#1对于代码是透明的,但我不是“背后”触发器的忠实粉丝,我不喜欢在任何地方传播业务规则。解决方案#3和#4依赖于Hibernate(但这可能不是问题)。如果您可以更改代码,解决方案#2是最简单,最便携的解决方案。如果这是一个选项,那将是我的选择。

答案 2 :(得分: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);
    }
}

答案 3 :(得分:1)

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

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插入数据时,这种类型会将字符串转换为大写。当hibernate选择数据时,会发生同样的事情。这个类的优点就是当我使用Criteria在serialNumber上选择时,只需将bean的get / set更改为大写。 Hibernate也将使我的参数大写,因为它将转换/应用表配置中定义的相同类型。

因此,我不需要记住手动大写我的序列号的所有搜索条件... hibernate为我照顾...这正是我想要在这里实现的!

我有一个演示所有这些内容的JUnit,但我认为我的回答太大了......

答案 4 :(得分:0)

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

它有3种不同的方法可以做到这一点。我认为最不具侵入性的方式是:

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