У нас есть некоторые столбцы с данными, которые должны всегда быть в верхнем регистре для обеспечения уникальности. Я задавался вопросом, в спящем режиме ли, может вызвать все такие столбцы к верхнему регистру через некоторое изменение конфигурационного файла?
Мы на самом деле используем пользовательский UserType для шифрования/дешифрования данных столбца для некоторой другой таблицы, но я полагал, что это будет излишеством только к верхнему регистру все...
С другой стороны, я думал об изменении моделей, таким образом, что все методы считывания/методы set будут верхний регистр любая приходящая и уходящая строка.
Худший (?) вариант развития событий должен изменить ограничение столбца Oracle для игнорирования регистра при проверке уникальности.
Какие-либо мысли?
Я решил реализовать 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 выбирает данные, происходит то же самое. Преимущество этого класса по сравнению с простым изменением get/set боба на прописные буквы заключается в том, что когда я использую Criteria для выбора по serialNumber. Hibernate также переведет мой параметр в верхний регистр, поскольку он будет приводить/применять тот же тип, который определен в конфигурации таблицы.
Таким образом, мне не нужно помнить о том, чтобы вручную переводить в верхний регистр все мои критерии поиска серийных номеров... hibernate позаботится об этом за меня... это именно то, чего я пытаюсь достичь!
У меня есть JUnit, который демонстрирует все эти вещи, но я думаю, что мой ответ и так слишком большой...
Предлагаю проверить эту страницу: http://forum.springsource.org/archive/index.php/t-18214.html
Для этого есть 3 разных способа. Я считаю, что наименее навязчивый способ заключается в следующем:
<property name="upperCaseName" formula="upper(name)" lazy="true"/>
Несколько решений:
UserType
для преобразования атрибута в верхний регистр. Решение №1 прозрачно для кода, но я не большой поклонник «скрытых» триггеров и не люблю распространять бизнес-правила повсюду. Решение №3 и №4 зависят от спящего режима (но это может не быть проблемой). Решение №2 - это самое простое и наиболее переносимое решение, если вы можете изменить код. Это был бы мой выбор, если это вариант.
Мне не известны какие-либо настройки конфигурации, чтобы сделать это возможным. Однако вы можете попробовать использовать перехватчик для исправления данных при вставке / обновлении, например:
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);
}
}