Wyliczenia w Hibernate


82

Często przydatne jest posiadanie pola w DAO, którego wartość pochodzi z wyliczenia Java. Typowym przykładem jest DAO logowania, w którym zwykle masz pole charakteryzujące użytkownika jako „NORMALNY” lub „ADMINISTRATOR”. W Hibernate użyłbym następujących 2 obiektów, aby przedstawić tę relację w (pół) bezpieczny sposób:

class User {
    String username;
    String passwd;
    UserType type;
}

class UserType {
    private enum Type {ADMIN, NORMAL};
    private String type;

    //Setters/Getters for Hibernate
    public void setType(String type);
    public String getType();

    //Setters/Getters for user
    public void setUserType(UserType.Type t);
    public UserType.Type getUserType();

    public static UserType fromType(UserType.Type t);
}

To działa, ale uważam, że klasa UserType jest brzydka i wymaga zbyt dużej biurokracji, aby przechowywać tylko kilka wartości. W idealnym przypadku Hibernate powinien obsługiwać pola wyliczeniowe bezpośrednio i utworzyć dodatkową tabelę do przechowywania wartości wyliczenia.

Moje pytanie brzmi: czy istnieje sposób bezpośredniego mapowania klasy wyliczenia w Hibernate? Jeśli nie, czy mój wzór przedstawiania wyliczeń jest wystarczająco dobry, czy czegoś mi brakuje? Jakich innych wzorców używają ludzie?

Odpowiedzi:


110

przy użyciu adnotacji hibernacji lub JPA:

class User {
   @Enumerated(EnumType.STRING)
   UserType type
}

UserType to po prostu standardowe wyliczenie języka Java 5.

Nie mogę sobie wyobrazić, że ogranicza się to tylko do adnotacji, ale tak naprawdę nie wiem, jak to zrobić z plikami HBM. Domyślam się, że może to być bardzo zależne od wersji, ale jestem prawie pewien, że wymagana jest hibernacja 3.2+.

edycja: jest to możliwe w hbm, ale jest trochę niechlujne, spójrz na ten wątek na forum


3
Czy @Enumerated (EnumType.ORDINAL), które mapowanie do int jest bardziej wydajne?
Lee Chee Kiam

4
prawdopodobnie jest bardziej wydajne, ale postawiłbym pieniądze na niemożność zmierzenia różnicy w rzeczywistym systemie. EnumType.ORDINAL jest w rzeczywistości wartością domyślną, jeśli po prostu wykonasz @Enumerated. Myślę, że większość ludzi (szczególnie DBA) preferuje nazwę wyliczenia w DB.
Gareth Davis,

1
Jak mogę zmienić długość kolumny dla tych wyliczeń? Próbowałem dodać adnotację kolumny, ale to nie jest honorowane?
Kannan Ekanath

2
Musisz zadać to jako kolejne pytanie.
Gareth Davis

2
Użyj ŁAŃCUCHA zamiast ORDINAL, ponieważ umożliwia to dodawanie dodatkowych elementów do Enum niezależnie od kolejności.
Matthew Daumen

14

Z dokumentacji Hibernate: http://www.hibernate.org/272.html

Możesz utworzyć nową definicję typu typedef dla każdego wyliczenia i odwołać się do tych typów w tagu property.

Przykładowe mapowanie - <type>tag wbudowany

  <property name='suit'>
    <type name="EnumUserType">
      <param name="enumClassName">com.company.project.Suit</param>
    </type>
  </property>

Przykładowe mapowanie - użycie <typedef>

  <typedef name="suit" class='EnumUserType'>
      <param name="enumClassName">com.company.project.Suit</param>
  </typedef>

  <class ...>
    <property name='suit' type='suit'/>
  </class>

Dzięki. Byłem już świadomy tego rozwiązania. Problem polega na tym, że wymaga, aby wszystkie wyliczenia używały wewnętrznych typów hibernacji, co może powodować problemy, jeśli używasz DAO jako DTO, jak w moim przypadku. Lepsze rozwiązanie opisano tutaj: hibernate.org/273.html
Georgios Gousios

1
Należy zauważyć, że w nowszych wersjach nazwą parametru jest enumClasszamiast enumClassName.
Ryan Ransford
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.