Wstęp
Czasem projekt wymaga, aby przechowywać w bazie danych dodatkowe informacje. Zwykle wymaga to utworzenia tabeli, oraz stworzenia klas do zarządzania tą tabelą. Obecnie najlepszym i zalecanym sposobem rozwiązania takiego problemu jest utworzenie klasy reprezentującej tabelę w bazie danych i mapowanie tej klasy za pomocą biblioteki Hibernate. Ogólnie mapowanie możemy realizować poprzez plik mapowania .hbm.xml lub poprzez adnotację. Zaleca się używanie adnotacji z uwagi na to, że nie musimy zmieniać pliku systemowego hibernate.cfg.xml. Operacje wykonywane na stworzonych obiektach to zazwyczaj dodawanie, usuwanie, modyfikacja i wyszukiwanie dlatego, aby wyeliminować konieczność implementacji metod umożliwiających wymienione operacje w API dostępnych jest kilka mechanizmów ułatwiających pracę na własnych obiektach bazodanowych. W tym rozdziale przedstawię dostępne sposoby zarządzania własnymi obiektami bazodanowymi.
Przykład mapowania
Załóżmy, że klient chce przechowywać informację o telefonach w swojej firmie. Stworzymy przykładową klasę Phone, którą wykorzystamy w kolejnych przykładach. W klasie są zawarte również mapowania.
Code Block | ||||
---|---|---|---|---|
| ||||
@Entity
@Table( name = "pm_phone" )
@SequenceGenerator( name = "pm_phone_id_seq", sequenceName = "pm_phone_id_seq" )
public class Phone
{
private Long id;
private String number;
private User owner;
@Id
@GeneratedValue( strategy = GenerationType.AUTO, generator = "pm_phone_id_seq" )
public Long getId()
{
return id;
}
public void setId( Long id )
{
this.id = id;
}
public String getNumber()
{
return number;
}
public void setNumber( String number )
{
this.number = number;
}
@ManyToOne( fetch = FetchType.LAZY )
@JoinColumn( name = "userid" )
public User getOwner()
{
return owner;
}
public void setOwner( User owner )
{
this.owner = owner;
}
} |
Adnotacja @Entity oznacza, że klasa będzie mapowana na tabelę w bazie danych i podczas uruchomienia systemu zostanie przeskanowana przez Hibernate. W @Table podajemy nazwę tabeli(patrz Konwencje). Adnotacja @SequenceGenerator pozwala utworzyć sequencer. Parametr name musi być unikalny w ramach całego systemu dlatego należy go ustawiać tak samo jak sequenceName(nazwa sequencera w bazie danych). W każdej mapowanej klasie wymagane jest co najmniej jedno pole oznaczone @Id, które zostanie kluczem głównym relacji. @GeneratedValue pozwala powiązać utworzony wcześniej sequencer z polem(powiązanie odbywa się za pomocą paremetru name, a nie sequenceName).
Info | ||
---|---|---|
| ||
W PlusWorkflow każda nowo tworzona tabela powinna posiadać przedrostek 'pm_'. Należy również pamiętać, żeby nazwa tabeli i seqencera nie była zbyt długa(max. 30 znaków), ponieważ niektóre bazy danych nie pozwalają na tworzenie długich nazw tabel. Dalej możemy zdefiniować dodatkowe opcje mapować - zachęcam do zajrzenia w dokumentacje Hiberante. W przykładzie mamy powiązanie z tabelą usertable poprzez pole owner. Pole number również zostanie zmapowane(zostanie utworzona kolumna w tabeli pm_phone). Jeżeli chcemy pominąć jakieś pole to korzystamy z @Transient. |
Info | ||
---|---|---|
| ||
Każda klasa oznaczona @Entity musi znajdować się w drzewie pakiety com.suncode |
CustomService
Najprostszym i najszybszym sposobem zarządzania obiektami bazodanowymi jest użycie klasy CustomService. Spójrzmy na przykład:
Code Block | ||||
---|---|---|---|---|
| ||||
CustomService<Phone, Long> ps = ServiceFactory.getCustomService( Phone.class, Long.class );
Phone p = new Phone();
p.setNumber( "777 777 777" );
ps.save( p );
List<Phone> phones = ps.getAll();
for ( Phone phone : phones )
{
log.debug( phone.getNumber() );
} |
Po pierwsze musimy pobrać odpowiednie serwis, jako parametry przekazujemy naszą klasę i klasę pola, której jest kluczem głównym. Tak stworzona klasa serwisu udostępnia wiele przydatnych funkcji pozwalających zarządzać naszym obiektem. W przykładzie zapisujemy nowy telefon w bazie danych, a następnie wczytujemy listę wszystkich telefonów z tabeli pm_phone.