2010-03-08 12 views
6

Mamy kilka kolumn z danymi, które zawsze muszą być pisane wielkimi literami, aby zapewnić wyjątkowość. Zastanawiam się, czy hibernacja może wymusić wszystkie takie kolumny na wielkie litery przez zmianę niektórych plików konfiguracyjnych?Czy Hibernacja może automatycznie wstawiać wielkimi literami kolumnę na temat odczytu/wstawiania przez konfigurację?

My faktycznie użyć niestandardowego UserType do szyfrowania/deszyfrowania danych kolumny do innej tabeli, ale pomyślałem, że byłoby przesadą tylko na wielkie wszystko ...

Alternatywnie, myślałem o modyfikację modele takie, że wszystkie moduły pobierające/ustawiające będą umieszczać wielkie litery na łańcuchach przychodzących i wychodzących.

Najgorszy (?) Scenariusz przypadku polega na zmodyfikowaniu ograniczenia kolumny Oracle, aby ignorować wielkość liter podczas sprawdzania wyjątkowości.

Jakieś myśli?

Odpowiedz

1

postanowiłem wdrożyć UserType ... to jest tak blisko do konfiguracji hibernacji jak mogę ... tutaj jest kod ...

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

Rozważmy ten element własności

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

Rozumowanie ... Gdy hibernacja wstawi dane, ten typ przekształci ciąg znaków w wielkie litery. Gdy hibernacja wybiera dane, dzieje się to samo. Zaletą tej klasy, która po prostu zmienia kolejność get/set to uppercase jest wszystko, gdy używam Criteria do wybrania na serialNumber. Hibernacja spowoduje również zapisanie wielkich liter mojego parametru, ponieważ będzie rzutować/stosować ten sam typ, co zdefiniowany w konfiguracji tabeli.

Dlatego nie muszę pamiętać, aby ręcznie wpisywać wielkie liczby wszystkich moich kryteriów wyszukiwania dla numerów seryjnych ... hibernate zajmuje się tym dla mnie ... dokładnie to próbuję osiągnąć tutaj!

Mam JUnit, który pokazuje wszystkie z tych rzeczy, ale myślę, że moja odpowiedź jest zbyt duża, jak to jest ...

1

Nie znam żadnych ustawień konfiguracyjnych, aby było to możliwe. Jednakże, można spróbować przy użyciu interceptor naprawić danych po insert/update, jak:

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); 
    } 
} 
+0

Mam przechwytywania zawierające inne "rzeczy", na które mogę wpaść na twój pomysł ... ale nie widzę pęcznienia logiki kilkunastu klas, które wymagają, aby niektóre z ich pól były wielkie. –

0

Sugeruję sprawdzanie tej strony: http://forum.springsource.org/archive/index.php/t-18214.html

Posiada 3 różne sposoby, aby to zrobić. Wierzę najmniej inwazyjnym sposobem jest taka:

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

Mogę się mylić, ale nie sądzę, że sztuczka z formułą zadziała w przypadku wstawiania lub aktualizacji (myślę, że Hibernate traktuje pola fomuli jako przejściowe i nie zapisuje ich w bazie danych). –

3

kilka rozwiązań:

  1. użyć wyzwalacz (nie poprzez konfigurację chociaż).
  2. Modyfikuj programy pobierające/ustawiające (ale nie przez konfigurację).
  3. Użyj UserType, aby przekształcić atrybut na duże litery.
  4. Użyj interceptor lub .

Rozwiązanie nr 1 jest przezroczysta dla kodu, ale nie jestem wielkim fanem „za plecami” wyzwalaczy i nie podoba mi się rozprzestrzeniać reguł biznesowych wszędzie. Rozwiązanie # 3 i # 4 są zależne od Hibernacji (ale może to nie być problem). Rozwiązanie # 2 jest najprostszym i najbardziej przenośnym rozwiązaniem, jeśli możesz zmienić kod. To byłby mój wybór, jeśli jest to opcja.

+0

Skłoniłem się również do # 2, ale szukałem konfiguracji hibernacji, która "po prostu zadziałałaby" ... –

+0

@ T Reddy Nic takiego, jak po wyjęciu z pudełka AFAIK. –

2

Znacznie czystsze podejście:

@Column(name = "DUMMY") 
@ColumnTransformer(read = "UPPER(DUMMY)") 
private String dummy 
Powiązane problemy