18. Aplikacja internetowa MVC w architekturze trójwarstwowej – Przykład 4, Postgres
18.1. Baza danych Postgres
W tej wersji umieścimy listę osób w tabeli bazy danych Postgres o nazwie 8.x [http://www.postgres.org]. Poniższe zrzuty ekranu pochodzą z klienta EMS PostgreSQL Manager Lite [http://www.sqlmanager.net/fr/products/postgresql/manager], bezpłatnego klienta administracyjnego do Postgres.
Baza danych nosi nazwę [dbpersonnes]. Zawiera ona tabelę [PERSONNES]:

Tabela [PERSONNES] będzie zawierała listę osób zarządzanych przez aplikację internetową. Została ona utworzona za pomocą następujących poleceń SQL:
Nie będziemy się szczegółowo zajmować tą tabelą, ponieważ jest ona analogiczna do omówionej wcześniej tabeli typu Firebird o nazwie [PERSONNES]. Należy jednak zauważyć, że nazwy kolumn i tabel są umieszczone w cudzysłowach. Ponadto w nazwach tych rozróżniana jest wielkość liter. Możliwe, że ten sposób działania Postgresu 8.x można skonfigurować. Nie zgłębiałem tej kwestii.
Tabela [PERSONNES] mogłaby mieć następującą zawartość:

Oprócz tabeli [PERSONNES] baza [dbpersonnes] zawiera obiekt zwany sekwencją o nazwie [SEQ_ID]. Generator ten generuje kolejne liczby całkowite, które wykorzystamy do nadania wartości kluczu głównego [ID] klasy [PERSONNES]. Przyjrzyjmy się przykładowi ilustrującemu jego działanie:
![]() |
![]() |
Można zauważyć, że wartość [Next value] z sekwencji [SEQ_ID] uległa zmianie (dwukrotne kliknięcie na nią + F5 w celu odświeżenia):
![]() |
Zlecenie SQL
pozwala zatem uzyskać następującą wartość sekwencji [SEQ_ID]. Wykorzystamy ją w pliku [personnes-postgres.xml], który gromadzi polecenia SQL wysłane na SGBD.
18.2. Projekt Eclipse warstw [dao] i [service]
Aby opracować warstwy [dao] i [service] naszej aplikacji z bazą danych Postgres 8.x, wykorzystamy następujący projekt Eclipse [spring-mvc-39]:

Projekt ten jest prostym projektem Java, a nie projektem internetowym opartym na Tomcat.
Folder [src]
Ten folder zawiera kod źródłowy warstw [dao] i [service]:

Wszystkie pliki, których nazwy zawierają ciąg znaków „[postgres]”, mogły zostać zmodyfikowane w stosunku do wersji Firebird lub pozostać bez zmian. Poniżej opisujemy pliki, które zostały zmodyfikowane.
Folder [database]
Ten folder zawiera skrypt służący do tworzenia bazy danych Postgres zawierającej dane osób:
![]()
Folder [lib]
Ten folder zawiera archiwa niezbędne do działania aplikacji:
![]() |
Warto zwrócić uwagę na obecność sterownika JDBC dla Postgres 8.x o numerze SGBD. Wszystkie te pliki archiwum stanowią część projektu Eclipse o numerze Classpath.
18.3. Warstwa [dao]
Warstwa [dao] wygląda następująco:

Przedstawiamy jedynie zmiany w stosunku do wersji [Firebird].
Plik mapowania [personne-postgres.xml] ma następującą postać:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<!-- uwaga – PostgreSQL 8 wymaga dokładnej pisowni nazw kolumn
et des tables ainsi que des guillemets autour de ces noms -->
<sqlMap>
<!-- alias klasy [Personne] -->
<typeAlias alias="Personne.classe"
type="istia.st.mvc.personnes.entites.Personne"/>
<!-- tabela mapowania [PERSONNES] – obiekt [Personne] -->
<resultMap id="Personne.map"
class="istia.st.mvc.personnes.entites.Personne">
<result property="id" column="ID" />
<result property="version" column="VERSION" />
<result property="nom" column="NOM"/>
<result property="prenom" column="PRENOM"/>
<result property="dateNaissance" column="DATENAISSANCE"/>
<result property="marie" column="MARIE"/>
<result property="nbEnfants" column="NBENFANTS"/>
</resultMap>
<!-- lista wszystkich osób -->
<select id="Personne.getAll" resultMap="Personne.map" > select "ID",
"VERSION", "NOM", "PRENOM", "DATENAISSANCE", "MARIE", "NBENFANTS" FROM
"PERSONNES"</select>
<!-- pobranie konkretnej osoby -->
<select id="Personne.getOne" resultMap="Personne.map" >select "ID",
"VERSION", "NOM", "PRENOM", "DATENAISSANCE", "MARIE", "NBENFANTS" FROM
"PERSONNES" WHERE "ID"=#wartość#</select>
<!-- dodaj osobę -->
<insert id="Personne.insertOne" parameterClass="Personne.classe">
<selectKey keyProperty="id">
SELECT nextval('"SEQ_ID"') as value
</selectKey>
insert into "PERSONNES"("ID", "VERSION",
"NOM", "PRENOM", "DATENAISSANCE", "MARIE", "NBENFANTS") VALUES(#id#,
#wersja#, #nazwisko#, #imię#, #dateNaissance#, #mąż#, #nbEnfants#)
</insert>
<!-- zaktualizuj dane osoby -->
<update id="Personne.updateOne" parameterClass="Personne.classe"> update
"PERSONNES" set "VERSION"=#wersja#+1, „NOM”=#nazwisko#, „PRENOM”=#imię#,
"DATENAISSANCE"=#dateNaissance#, „MARIE”=#żona#, „NBENFANTS”=#nbEnfants#
WHERE "ID"=#id# oraz „VERSION”=#wersja#</aktualizacja>
<!-- usunięcie osoby -->
<delete id="Personne.deleteOne" parameterClass="int"> delete FROM
"PERSONNES" WHERE "ID"=#wartość# </delete>
</sqlMap>
Zawartość jest identyczna jak w pliku [personnes-firebird.xml], z wyjątkiem następujących szczegółów:
- nazwy kolumn i tabel są ujęte w cudzysłowy, a w tych nazwach rozróżniana jest wielkość liter
- kolejność SQL „ Personne.insertOne ” uległa zmianie w wierszach 34–41. Sposób generowania klucza głównego w Postgresie różni się od tego stosowanego w Firebirdzie:
- wiersz 36: kolejność SQL [SELECT nextval('"SEQ_ID"')] określa klucz główny. Składnia [as value] jest obowiązkowa. [value] oznacza uzyskany klucz. Wartość ta zostanie przypisana do pola obiektu [Personne] wskazanego przez atrybut [keyProperty] (wiersz 35), w tym przypadku do pola [id].
- Polecenia SQL zawarte w tagu <insert> są wykonywane w kolejności, w jakiej występują. Zatem polecenie SELECT jest wykonywane przed poleceniem INSERT. W momencie operacji wstawiania pole [id] obiektu [Personne] zostanie zatem zaktualizowane przez polecenie SQL SELECT.
- wiersze 38–40: wstawienie obiektu [Personne]
Klasa implementacyjna [DaoImplCommon] warstwy [dao] jest tą samą, którą analizowano w wersji [Firebird].
Konfiguracja warstwy [dao] została dostosowana do SGBD i [Postgres]. W związku z tym plik konfiguracyjny [spring-config-test-dao-postgres.xml] ma następującą treść:
<?xml version="1.0" encoding="ISO_8859-1"?>
<!DOCTYPE beans SYSTEM "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- źródło danych DBCP -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName">
<value>org.postgresql.Driver</value>
</property>
<property name="url">
<value>jdbc:postgresql:dbpersonnes</value>
</property>
<property name="username">
<value>postgres</value>
</property>
<property name="password">
<value>postgres</value>
</property>
</bean>
<!-- SqlMapCllient -->
<bean id="sqlMapClient"
class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource">
<ref local="dataSource"/>
</property>
<property name="configLocation">
<value>classpath:sql-map-config-postgres.xml</value>
</property>
</bean>
<!-- klasa dostępu do warstwy [dao] -->
<bean id="dao" class="istia.st.mvc.personnes.dao.DaoImplCommon">
<property name="sqlMapClient">
<ref local="sqlMapClient"/>
</property>
</bean>
</beans>
- wiersze 5–19: bean [dataSource] odnosi się teraz do bazy [Postgres] [dbpersonnes], której administratorem jest [postgres] z hasłem [postgres]. Czytelnik powinien dostosować tę konfigurację do własnego środowiska.
- wiersz 31: klasa [DaoImplCommon] jest klasą implementacyjną warstwy [dao]
Po wprowadzeniu tych zmian można przejść do testów.
18.4. Testy warstw [dao] i [service]
Testy warstw [dao] i [service] są takie same jak dla wersji [Firebird]. Uruchommy SGBD Postgres, a następnie testy w Eclipse. Uzyskane wyniki są następujące:
![]() |
Widać, że testy zakończyły się powodzeniem w przypadku implementacji [DaoImplCommon]. Nie będziemy musieli tworzyć klasy pochodnej, jak to było konieczne w przypadku SGBD i [Firebird].
18.5. Testy aplikacji [web]
Aby przetestować aplikację internetową z wykorzystaniem SGBD i [Postgres], tworzymy projekt Eclipse o nazwie [mvc-personnes-04B] w sposób analogiczny do tego, który zastosowano przy tworzeniu projektu [mvc-personnes-03B] z bazą danych Firebird (patrz paragraf 17.7). Nie musimy jednak ponownie tworzyć archiwów [personnes-dao.jar] i [personnes-service.jar]. W rzeczywistości nie wprowadziliśmy żadnych zmian w klasach w stosunku do projektu [mvc-personnes-03B]. Po prostu archiwum [personnes-dao.jar] zawiera klasę [DaoImplFirebird], która stała się zbędna.

Wdrażamy projekt internetowy [mvc-personnes-04B] w środowisku Tomcat:
![]() | ![]() |
Jesteśmy gotowi do przeprowadzenia testów . Zawartość tabeli [PERSONNES] wygląda wówczas następująco:

Tomcat został uruchomiony. W przeglądarce wpisujemy adres URL [http://localhost:8080/mvc-personnes-04B]:

Dodajemy nową osobę za pomocą linku [Ajout]:
![]() | ![]() |
Sprawdzamy, czy wpis został dodany do bazy danych:

Użytkownik jest proszony o przeprowadzenie dalszych testów [modification, suppression].








