Polish | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Spis treści
WstępCzasem 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 mapowaniaZałóż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.
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).
CustomServiceNajprostszym i najszybszym sposobem zarządzania obiektami bazodanowymi jest użycie klasy CustomService. Spójrzmy na przykład:
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.
Service (zaawansowany)Jeżeli mamy bardziej złożony problem i podczas operacji na bazie danych powinny zostać wywołane dodatkowe akcje lub wykonanie operacji na naszym obiekcie jest bardziej złożone to możemy utworzyć własną klasę Service. W celu utworzenia klasy Service musimy zbudować cały mechanizm na, który składają się dwie warstwy - DAO i Service. Całość będzie zawierała dwa interfejsy i dwie klasy implementujące. Zacznijmy od warstwy DAO
Ważne jest tutaj to, że w warstwie DAO nie zajmujemy się transakcjami tzn. podczas wywołania funkcji DAO transakcja musi być rozpoczęta(dlatego potrzebujemy klasy Service). W DAO możemy dodać własne funkcje które wykonują jakieś specyficzne operacje bazodanowe(nie implementujemy tutaj logiki biznesowej, walidacji itp.). Z nadklasy otrzymujemy wiele przydatnych metod, oraz jak widać powyżej możemy pobrać sesję. Jeżeli nasz serwis ma umożliwiać tylko operacje odczytu możemy zamiast EditableDao i HibernateEditableDao użyć odpowiedznio BaseDao i HibernateBaseDao. Warstwa Service:
Zawsze obowiązkowo musimy napisać metodę setDao, która w połączeniu z adnotacją @Autowired spowoduje załadowanie odpowiedniej implementacji do naszego obiektu dao. Pamiętamy o dodaniu adnotacji @Transactional do funkcji, w których wykonujemy operacje bazodanowe. Tam gdzie w DAO i w Service jest używany typ Long to wynika to z tego że takiego typu jest pole które jest Id w modelu (tu klasa Phone). Jeśli typ pola które jest Id będzie inne to analogicznie trzeba zastosować też inny typ w DAO i Service.
Przydatne zasoby:
|
English | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Table of contents
IntroductionSometimes a project requires that you store additional information in the database. This usually requires the creation of a table, and the creation of classes to manage this table. Currently, the best and recommended way to solve such a problem is to create a class representing a table in the database, and map this class using the Hibernate library. In general, we can implement the mapping through a .hbm.xml mapping file or through an annotation. It is recommended to use annotation due to the fact that we do not have to change the system file hibernate.cfg.xml. The operations performed on the created objects are typically adding, deleting, modifying and searching therefore, to eliminate the need to implement methods to enable the above-mentioned operations, several mechanisms are available in the API to facilitate working on custom database objects. In this chapter, I will present the available ways to manage your own database objects. Example of mappingSuppose a customer wants to store information about phones in his company. We will create an example Phone class, which we will use in the following examples. The class also includes mappings.
The @Entity annotation means that the class will be mapped to a table in the database and will be scanned by Hibernate during system startup. In @Table we specify the name of the table(see Conventions). The @SequenceGenerator annotation allows you to create a sequencer. The name parameter must be unique within the entire system, so it should be set the same as sequenceName(the name of the sequencer in the database). At least one field marked @Id is required in each mapped class, which will become the primary key of the relationship. The @GeneratedValue allows you to bind a previously created sequencer to a field(the binding is done using the name paremeter, not sequenceName).
CustomServiceThe easiest and fastest way to manage database objects is to use the CustomService class. Let's look at an example:
First, we need to download the appropriate service, as parameters we transfer our class and the class of the field of which it is the primary key. The service class created in this way provides many useful functions to manage our object. In the example, we save the new phone in the database, and then load the list of all phones from the pm_phone table.
Service (advanced)If we have a more complex problem and additional actions should be called during database operations or the execution of operations on our object is more complex then we can create our own Service class. In order to create the Service class, we need to build the whole mechanism on which consists of two layers - DAO and Service. The whole thing will contain two interfaces and two implementation classes. Let's start with the DAO layer
The important thing here is that in the DAO layer we do not deal with transactions, i.e. when calling a DAO function, the transaction must be started (that's why we need a Service class). In DAO we can add our own functions that perform some specific database operations (we do not implement business logic, validation, etc. here). From the superclass we get many useful methods, and as you can see above we can retrieve a session. If our service is to allow only read operations we can use BaseDao and HibernateBaseDao instead of EditableDao and HibernateEditableDao respectively. Service Layer:
It is always mandatory for us to write a setDao method, which, combined with the @Autowired annotation, will load the appropriate implementation into our dao object. Remember to add the @Transactional annotation to the functions where we perform database operations. Where the type Long is used in the DAO and in the Service it is because that is the type of the field that is the Id in the model (here the Phone class). If the type of the field which is the Id will be different then, similarly, you also need to use a different type in DAO and Service.
Useful resources:
|