Can Hibernate automatically smooth column when reading / pasting through configuration?

We have several columns with data that should always be uppercase to ensure uniqueness. I was wondering if hibernate can force all such columns to be uppercase by changing the configuration file?

In fact, we use the user-defined type UserType to encrypt / decrypt the column data for some other table, but I decided that it would be superfluous only for the capital letters all ...

Alternatively, I was thinking of modifying the models so that all getters / setters delay any line going and going.

The worst (?) Scenario is to change the restriction of an Oracle column to ignore case when checking for uniqueness.

Any thoughts?

+6
oracle orm hibernate
source share
5 answers

I decided to implement UserType ... it is as close as possible to the sleep mode configuration, since I can get ... here the code ...

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; } } 

Consider this property element

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

So, reasoning ... When hibernate inserts data, this type converts the string to uppercase. When hibernate selects the data, the same thing happens. The advantage of this class is that it just changed the bean get / set value to uppercase, and all this when I use the criteria for selection in serialNumber. Hibernate will also smooth out my parameter, as it will apply / apply the same type as in the table configuration.

So I don’t have to forget to manually write down all my search criteria for serial numbers ... hibernate will take care of this for me ... this is exactly what I am trying to achieve here!

I have a JUnit that demonstrates all this, but I think my answer is too big as it is ...

+1
source share

A few solutions:

  • Use a database trigger (but not through configuration).
  • Change getter / setters (but not through configuration).
  • Use UserType to convert the attribute to uppercase.
  • Use an interceptor or event listener .

Solution # 1 is transparent to code, but I'm not a big fan of triggers “behind my back,” and I don't like to distribute business rules everywhere. Decision number 3 and number 4 depends on Hibernate (but this may not be a problem). Solution # 2 is the easiest and most portable solution if you can change the code. That would be my choice if this is an option.

+3
source share

Cleaner approach:

 @Column(name = "DUMMY") @ColumnTransformer(read = "UPPER(DUMMY)") private String dummy 
+2
source share

I am not aware of the configuration settings to make this possible. However, you can try using an interceptor to correct the data when inserting / updating, for example:

 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); } } 
+1
source share

I suggest checking this page: http://forum.springsource.org/archive/index.php/t-18214.html

It has 3 different ways to do this. I believe this is the least intrusive way:

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

All Articles