dev garden

when technology meets nature

@GeneratedValue oraz @SequenceGenerator – czyli sekwencje w hibernate

| 1 Comment

Tworzenie mojego projektu* rozpocząłem od zdefiniowania bazy danych, tabel w bazie oraz odpowiednich relacji między tabelami, na koniec dodałem sekwencje. Wszystko wygląda pięknie, i tak w teorii działa.

Jak każdy programista jestem leniwy, zamiast tworzyć mapowania w moim IDE o wiele lepiej wygenerować je wprost z bazy. W IntelliJ robi się łatwo o ile znajdziemy odpowiednią opcję o czym pisałem jakiś czas temu.  Niestety szybko przekonałem się, że nie jest to idealne odwzorowanie moich tabel. Nie wiedzieć czemu IntelliJ zapomniał zaimportować sekwencje zadeklarowane w bazie, co skutkowało wystąpieniem szeregu błędów podczas prób zapisania danych w bazie, w szczególności wyróżnia się jeden:

org.springframework.web.util.NestedServletException: Request processing failed;
  nested exception is org.springframework.orm.hibernate3.HibernateSystemException:
    ids for this class must be manually assigned before calling save():
       com.darekzon.coffeine.domain.Category;
  nested exception is org.hibernate.id.IdentifierGenerationException:
    ids for this class must be manually assigned before calling save():
       com.darekzon.coffeine.domain.Category

Aby problemy przestały występować wystarczy z palca podpiąć sekwencje do konkretnego pola, robimy to przez zastosowanie adnotacji @GeneratedValue przy polu którego wartości mają być generowane przez sekwencje.

Kod wygląda następująco:

import javax.persistence.*;
import java.io.Serializable;
 
@Entity
@Table(schema = "public", name = "category")
public class Category implements Serializable {
 
private Long id;
 
@Id
@Column(name = "id", nullable = false, length = 19)
@SequenceGenerator(name = "category_seq", sequenceName = "category_id_seq")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "category_seq")
public Long getId() {
return id;
}
 
public void setId(Long id) {
this.id = id;
}
 
private String name;
 
@Basic
@Column(name = "name", nullable = false, length = 30)
public String getName() {
return name;
}
 
public void setName(String name) {
this.name = name;
}
 
}

Pierwsze co robimy aby dodać generator to wskazanie która sekwencja generuje dane dla naszego pola, czyli adnotacja @SequenceGenerator,  podajemy dla niej dwie wartości, pierwsza to nazwa sekwencji jaka obowiązywać będzie w zakresie naszej klasy, natomiast druga to nazwa sekwencji w bazie.

Po skonfigurowaniu sekwencji mówimy hibernate-owi, że nasze -pole będzie otrzymywać automatycznie wartość korzystając z @GeneratedValue. Dla adnotacji @GeneratedValue musimy podać strategię tworzenia nowych wartości (z racji, że jest to sekwencja wybieramy SEQUENCE)  i oczywiście generator który te wartości będzie wskazywał, jako generator podajemy nazwę którą wcześniej wpisaliśmy w @SequenceGenerator.

Po tym zabiegu wszystko powinno działać jak trzeba.

Swoją drogą muszę się przestawić na tworzenie Entity Beanów a potem eksportowanie to do bazy danych, na pewno przyśpieszy to tworzenie projektu a przy okazji nie będę musiał tworzyć bazy danych (co uważam za zajęcie mało interesujące).

* samo tworzenie, nie wliczyłem w to zbieranie wymagań i wstępne projekty i inne bzdurki ;)

Author: darek

Programista, z zamiłowania fotograf. Interesuje się różnymi aspektami programowania oraz językiem Java niemal w każdym jego wydaniu. Amator grejpfrutów oraz dobrego humoru. W wolnych chwilach czyta ciekawe książki(grails, gwt, objective-c) nie tylko informatyczne, ale również popularno naukowe oraz s-f

One Comment

  1. Jedno ale:
    Jak nie dasz strategy = GenerationType.AUTO może się okazać, że Hibernate nie korzysta ze wskazanej sekwencji – i, z powodów, które są zupełnie niejasne i absolutnie tajemnicze, wartości klucza w tabeli zaczynają się od 5051 a sekwencja ani drgnie. Z drugiej strony wskazanie strategii AUTO, że ma korzystać z sekwencji użytkownika, a nie z ogólnej, na pierwszy rzut oka kompletnie nielogiczne, działa wyśmienicie.
    Czary…
    Pozdrawiam.
    Tarrin

Dodaj komentarz

Required fields are marked *.

*