Tworzenie samodzielnej aplikacji ze Spring Framework i Hibernate w NetBeans IDE 6.9

Z Jacek Laskowski - Wiki Projektanta Java EE

Artykuł przedstawia kroki niezbędne do stworzenia samodzielnej aplikacji korzystającej ze Spring Framework i Hibernate w zintegrowanym środowisku programistycznym NetBeans IDE 6.9.

W poprzednich artykułach przedstawiłem tworzenie samodzielnej aplikacji ze Spring Framework - Tworzenie samodzielnej aplikacji ze Spring Framework w NetBeans IDE 6.9 oraz samodzielnej aplikacji z Hibernate - Tworzenie samodzielnej aplikacji z Hibernate w NetBeans IDE 6.9. Można było zauważyć mnogość plików konfiguracyjnych - każdy wymagał własnego, głównego pliku konfiguracyjnego oraz kilku pomocniczych w przypadku Hibernate. Zarządzanie nimi może przyprawić o ból głowy. To będzie jedna z dwóch zalet połączenia obu rozwiazań. Kolejną będzie ukrycie wykorzystania Hibernate przez Spring, tak że możliwa migracja do innego dostawcy dostępu do bazy sprowadzi się jedynie do zmian w pliku konfiguracyjnym bez zmian w samym kodzie źródłowym. Spring, który udostępnia rozwiązania wspierające integrację z Hibernate, bądź jego zamiennikami, zniesie z nas obowiązek poznania detali technicznych (dostęp do bazy danych, czy obsługa danych) do oprogramowania logiki biznesowej. W sumie, Spring i Hibernate, uproszczą tworzenie aplikacji korporacyjnych na wzór serwera aplikacyjnego Java EE.

Wymagane oprogramowanie:

Kompletny projekt jest dostępny jako SpringHibernateApplication.zip.

Spis treści

Stworzenie projektu SpringHibernateApplication

Rozpoczniemy od wczytania istniejącej aplikacji SpringApplication z artykułu Tworzenie samodzielnej aplikacji ze Spring Framework w NetBeans IDE 6.9.

Otwieramy (importujemy) projekt SpringApplication do NetBeans IDE - Cmd+Shirt+O lub File > Open Project... lub wybieramy Open Project... z menu kontekstowego w widoku Projects.

Plik:springhibernatenetbeans69-openproject.png

Z okienka dialogowego wybieramy katalog z naszym projektem i zaznaczamy opcję "Open as Main Project".

Plik:springhibernatenetbeans69-openproject-springapplication.png

Wciskamy przycisk Open Project.

Plik:springhibernatenetbeans69-springapp-otwarty.png

Z menu kontekstowego projektu wybieramy Rename....

Plik:springhibernatenetbeans69-rename.png

Podajemy nową nazwę projektu SpringHibernateApplication oraz (opcjonalnie) zaznaczamy opcję Also Rename Project Folder.

Plik:springhibernatenetbeans69-renameproject.png

Wciskamy przycisk Rename.

Przypisanie własnej biblioteki Hibernate-3.5.3

W artykule Tworzenie samodzielnej aplikacji z Hibernate w NetBeans IDE 6.9 zdefiniowaliśmy własną bibliotekę Hibernate-3.5.3, która zawierała wszystkie niezbędne pliki jar do poprawnej pracy Hibernate 3.5.3 (domyślnie dostarczana biblioteka Hibernate jest niepełna i wymaga dodania kilku pomocniczych jarów). Przypiszemy ją do naszego nowego projektu.

Postępujemy tak, jak opisano w Dodanie własnej biblioteki Hibernate-3.5.3 we wspomnianym artykule.

Dobrym zwyczajem jest sprawdzenie, czy nasze zmiany wciąż gwarantują poprawność uruchomienia aplikacji. Klawiszem F6 uruchamiamy nasz projekt.

run:
Jul 11, 2010 5:39:17 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2c091cee: startup date [Sun Jul 11 17:39:17 CEST 2010]; root of context hierarchy
Jul 11, 2010 5:39:19 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Jul 11, 2010 5:39:21 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5117f31e: defining beans [ziarno]; root of factory hierarchy
Komunikat: Działa!
BUILD SUCCESSFUL (total time: 5 seconds)

Stworzenie encji - Klient

Postępujemy zgodnie z instrukcjami podanymi w Stworzenie encji - Klient w artykule Tworzenie samodzielnej aplikacji z Hibernate w NetBeans IDE 6.9.

Odwzorowanie encji Klient na tabelę w pliku konfiguracyjnym Hibernate - Klient.hbm.xml

Postępujemy zgodnie z instrukcjami podanymi w Odwzorowanie encji na tabelę w pliku konfiguracyjnym Hibernate - hibernate.hbm.xml w artykule Tworzenie samodzielnej aplikacji z Hibernate w NetBeans IDE 6.9 z tą różnicą, że nazwa pliku mapującego będzie tym razem Klient.hbm.xml, który zapisujemy w tym samym katalogu, w którym stworzyliśmy klasę encji - src/model.

Plik:springhibernatenetbeans69-new-hibernate-mapping-wizard.png

Określenie kontraktu bazodanowego - dao.KlientDao

Wzorzec projektowy DAO (ang. Data Access Object) określa kontrakt (interfejs) dostępu do danych składowanych w repozytorium danych. Może to być dowolne repozytorium/składnica danych, więc detale infrastrukturalne - czy pracujemy z systemem plików, czy bazą danych, nie "wyciekają" przez tworzony kontrakt. Możnaby powiedzieć, że to, co oferuje DAO, to jedynie/aż udostępnione mechanizmy (metody) obsługi danych.

W naszym przypadku określimy 4 możliwe operacje na składnicy danych - tworzenie nowego klienta (create), odszukanie klienta po jego numerze (read), aktualizacja danych klienta (update) i skasowanie klienta (delete). Wszystkie z zaproponowanych metod nie mówi nic o faktycznej realizacji składnicy danych (wciąż nie wiemy, czy pracujemy z relacyjną bazą danych, a może obiektową bazą danych, czy po prostu systemem plików, albo zewnętrzną usługą, z którą kontaktujemy się za pomocą REST).

package dao;
 
import model.Klient;
 
/**
 * @author Jacek Laskowski
 */
public interface KlientDao {
    public void create(Klient klient);
    public Klient read(String klientNr);
    public void update(Klient klient);
    public void delete(Klient klient);
}

Realizacja kontraktu bazodanowego - dao.HibernateKlientDaoImpl

Technicznie, realizacja kontraktu bazodanowego sprowadza się do implementacji interfejsu DAO - dao.KlientDao. Jest to określenie działania metod obsługujących repozytorium danych i dopiero tutaj dowiadujemy się/określamy z jakim konkretnie repozytorium danych pracujemy. W naszym przypadku będzie to baza danych z pomocą Hibernate, ale moglibyśmy wyobrazić sobie implementację DAO na bazie JDO, iBatis, czy wręcz JDBC, lub jeszcze bardziej egzotyczne repozytoria jak (nietransakcyjny) system plików.

Definiujemy klasę dao.HibernateKlientDaoImpl, której zadaniem jest obsługa danych w bazie danych z pomocą Hibernate. W Springu mamy do dyspozycji klasę org.springframework.orm.hibernate3.support.HibernateDaoSupport, która ukrywa nam niuanse integracji Springa z Hibernate (na naszym poziomie zaawansowania wystarczy wiedza, że udostępnia metody konfigurujące fabrykę sesji - public final void setSessionFactory(org.hibernate.SessionFactory sessionFactory) i szablony Hibernate - public final void setHibernateTemplate(HibernateTemplate hibernateTemplate)).

Poza rozszerzeniem klasy org.springframework.orm.hibernate3.support.HibernateDaoSupport, korzystamy z adnotacji @Transactional, za pomocą której określamy, które metody są objęte aktywną transakcją.

Implementację metod DAO opieramy na szablonach Hibernate (za pomocą metody public final HibernateTemplate getHibernateTemplate()).

UWAGA: Dwie z metod nie zostały zaimplementowane i ich realizację pozostawiam jako rodzaj testu weryfikującego zrozumienie dotychczasowego materiału.

package dao;
 
import model.Klient;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Transactional;
 
/**
 * @author Jacek Laskowski
 */
public class HibernateKlientDaoImpl extends HibernateDaoSupport implements KlientDao {
 
    @Transactional
    public void create(Klient klient) {
        getHibernateTemplate().save(klient);
    }
 
    @Transactional
    public void delete(Klient klient) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
 
    @Transactional(readOnly=true)
    public Klient read(String klientNr) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
 
    @Transactional
    public void update(Klient klient) {
        getHibernateTemplate().update(klient);
    }
}

Rozszerzenie konfiguracji Spring o konfigurację Hibernate

Tworzymy nowy plik konfiguracyjny Springa - beans-hibernate.xml, który będzie zawierał konfigurację dotyczącą Hibernate.

Z okienka dialogowego New File (Cmd+n lub z menu kontekstowego projektu - New > Other...) wybieramy Spring XML Configuration File w kategorii Other.

Plik:springhibernatenetbeans69-springxmlconfigurationfile.png

Wciskamy przycisk Next >.

Podajemy nazwę pliku konfiguracyjnego beans-hibernate w polu File Name.

Plik:springhibernatenetbeans69-new-spring-xml-config-file.png

Wciskamy przycisk Next >.

Wybieramy dwie przestrzenie nazewnicze aop i tx w panelu Spring namespaces.

Plik:springhibernatenetbeans69-spring-namespaces.png

Wciskamy przycisk Finish.

Plik modyfikujemy o deklaracje automatycznego wiązania między beanami (bodajże pierwsze moje użycie na piśmie!) springowymi - atrybut default-autowire, obsługę adnotacji transakcyjnych w beanach, zestaw beanów springowych do obsługi Hibernate - dataSource (dostęp do bazy danych), sessionFactory (fabryka sesji Hibernate), transactionManager (zarządca transakcji) i hibernateTemplate (włączenie szablonów Hibernate), aby całość podsumować kolejnym beanem korzystającym z tych definicji klientDao.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
          http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
       default-autowire="byName">
 
    <tx:annotation-driven />
 
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
        <property name="url" value="jdbc:derby://localhost:1527/FIRMA;create=true" />
        <property name="username" value="app" />
        <property name="password" value="app" />
    </bean>
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="mappingResources">
            <list>
                <value>model/Klient.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.DerbyDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
            </props>
        </property>
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" />
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate" />
 
    <bean name="klientDao" class="dao.HibernateKlientDaoImpl" />
</beans>

Uruchomienie produkcyjne - Spring i Hibernate połączeni

Skoro Hibernate występuje w roli realizującego kontrakt DAO, a Spring zarządza przestrzenią komponentów (ziaren springowych), uruchomienie aplikacji sprowadza się do pozyskania referencji do ziarna klientDao, a wykonywane operacje będą angażowały Hibernate do odwzorowania obiektu Klienta na odpowiadającą mu tabelę i spowrotem (wszystko opisane w pliku mapującym hbm.xml).

package springapplication;
 
import dao.KlientDao;
import model.Klient;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
public class Main {
 
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans-hibernate.xml");
        KlientDao klientDao = context.getBean("klientDao", KlientDao.class);
        Klient jacek = new Klient("Jacek", "Laskowski");
        klientDao.create(jacek);
    }
}

Wciskamy F6 i analizujemy wynik działania aplikacji, w którym zobaczymy aktywację Springa, Hibernate i zapisanie nowego klienta do bazy danych. Czyżby?

run:
Jul 12, 2010 11:33:42 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@a4a63d8: startup date [Mon Jul 12 23:33:42 CEST 2010]; root of context hierarchy
Jul 12, 2010 11:33:42 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans.xml]
Jul 12, 2010 11:33:42 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans-hibernate.xml]
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException:
Unexpected exception parsing XML document from class path resource [beans-hibernate.xml]; 
nested exception is java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:412)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
        at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:143)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:178)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:149)
        at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:212)
        at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:126)
        at org.springframework.context.support.AbstractXmlApplicationContext.loadBeanDefinitions(AbstractXmlApplicationContext.java:92)
        at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.java:130)
        at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.java:465)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:395)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
        at springapplication.Main.main(Main.java:10)
...
Caused by: java.lang.ClassNotFoundException: org.aopalliance.intercept.MethodInterceptor
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
        ... 35 more
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

Okazuje się, że zdefiniowane biblioteki nie są wystarczające na nasze potrzeby i konieczne będzie zdefiniowanie zależności (biblioteki) dostępnej podczas uruchomienia aplikacji.

Z menu kontekstowego projektu wybieramy menu Properties i w kategorii Libraries wybieramy zakładkę Run, aby tam dodać wymaganą zależność - com.springsource.org.aopalliance-1.0.0.jar (właśnie w takich przypadkach, użycie Apache Maven, Apache Ivy, czy innego rozwiązania samodzielnie pobierającego zależności byłoby nieocenione).

Plik:springhibernatenetbeans69-properties-libraries-run.png

Z tak zdefiniowanym środowiskiem jesteśmy gotowi do ponownego uruchomienia aplikacji. Wciskamy ponownie przycisk F6.

run:
...
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataSource' defined in class path resource [beans-hibernate.xml]:
Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception;
nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [org.apache.derby.jdbc.ClientDriver]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1353)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1076)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:872)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:423)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
        at springapplication.Main.main(Main.java:10)
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception;
nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [org.apache.derby.jdbc.ClientDriver]
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:102)
        at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1350)
        ... 13 more
Java Result: 1
BUILD SUCCESSFUL (total time: 1 second)

Szybka analiza sytuacji i już po chwili wiadomo, że brakuje klas sterownika bazy danych. Dodajemy kolejną zależność projektową - derbyclient.jar. Dodajemy bibliotekę Apache Derby.

Plik:springhibernatenetbeans69-derbyclient-jar.png

Ponownie uruchamiamy aplikację klawiszem F6.

run:
Jul 13, 2010 7:30:33 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@a4a63d8: startup date [Tue Jul 13 19:30:33 CEST 2010]; root of context hierarchy
Jul 13, 2010 7:30:33 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [beans-hibernate.xml]
Jul 13, 2010 7:30:34 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5982bcde: defining beans
[org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,
org.springframework.transaction.interceptor.TransactionInterceptor#0,
org.springframework.transaction.config.internalTransactionAdvisor,dataSource,sessionFactory,transactionManager,hibernateTemplate,klientDao]; root of factory hierarchy
Jul 13, 2010 7:30:34 PM org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: org.apache.derby.jdbc.ClientDriver
37 [main] INFO org.hibernate.cfg.Environment - Hibernate 3.5.3-Final
40 [main] INFO org.hibernate.cfg.Environment - hibernate.properties not found
43 [main] INFO org.hibernate.cfg.Environment - Bytecode provider name : javassist
51 [main] INFO org.hibernate.cfg.Environment - using JDK 1.4 java.sql.Timestamp handling
305 [main] INFO org.hibernate.cfg.HbmBinder - Mapping class: model.Klient -> Klient
Jul 13, 2010 7:30:34 PM org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
391 [main] INFO org.hibernate.connection.ConnectionProviderFactory - Initializing connection provider: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider
903 [main] INFO org.hibernate.cfg.SettingsFactory - RDBMS: Apache Derby, version: 10.5.3.0 - (802917)
903 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC driver: Apache Derby Network Client JDBC Driver, version: 10.6.1.0 - (938214)
934 [main] INFO org.hibernate.dialect.Dialect - Using dialect: org.hibernate.dialect.DerbyDialect
1028 [main] INFO org.hibernate.transaction.TransactionFactoryFactory - Transaction strategy: org.springframework.orm.hibernate3.SpringTransactionFactory
1031 [main] INFO org.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured
(in JTA environment, use of read-write or transactional second-level cache is not recommended)
1033 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic flush during beforeCompletion(): disabled
1034 [main] INFO org.hibernate.cfg.SettingsFactory - Automatic session close at end of transaction: disabled
1037 [main] INFO org.hibernate.cfg.SettingsFactory - Scrollable result sets: enabled
1037 [main] INFO org.hibernate.cfg.SettingsFactory - JDBC3 getGeneratedKeys(): disabled
1037 [main] INFO org.hibernate.cfg.SettingsFactory - Connection release mode: auto
1038 [main] INFO org.hibernate.cfg.SettingsFactory - Default batch fetch size: 1
1038 [main] INFO org.hibernate.cfg.SettingsFactory - Generate SQL with comments: disabled
1038 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL updates by primary key: disabled
1038 [main] INFO org.hibernate.cfg.SettingsFactory - Order SQL inserts for batching: disabled
1038 [main] INFO org.hibernate.cfg.SettingsFactory - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
1042 [main] INFO org.hibernate.hql.ast.ASTQueryTranslatorFactory - Using ASTQueryTranslatorFactory
1042 [main] INFO org.hibernate.cfg.SettingsFactory - Query language substitutions: {}
1042 [main] INFO org.hibernate.cfg.SettingsFactory - JPA-QL strict compliance: disabled
1042 [main] INFO org.hibernate.cfg.SettingsFactory - Second-level cache: enabled
1042 [main] INFO org.hibernate.cfg.SettingsFactory - Query cache: disabled
1042 [main] INFO org.hibernate.cfg.SettingsFactory - Cache region factory : org.hibernate.cache.impl.NoCachingRegionFactory
1042 [main] INFO org.hibernate.cfg.SettingsFactory - Optimize cache for minimal puts: disabled
1042 [main] INFO org.hibernate.cfg.SettingsFactory - Structured second-level cache entries: disabled
1063 [main] INFO org.hibernate.cfg.SettingsFactory - Echoing all SQL to stdout
1064 [main] INFO org.hibernate.cfg.SettingsFactory - Statistics: disabled
1064 [main] INFO org.hibernate.cfg.SettingsFactory - Deleted entity synthetic identifier rollback: disabled
1064 [main] INFO org.hibernate.cfg.SettingsFactory - Default entity-mode: pojo
1064 [main] INFO org.hibernate.cfg.SettingsFactory - Named query checking : enabled
1064 [main] INFO org.hibernate.cfg.SettingsFactory - Check Nullability in Core (should be disabled when Bean Validation is on): enabled
1148 [main] INFO org.hibernate.impl.SessionFactoryImpl - building session factory
1472 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not binding factory to JNDI, no JNDI name configured
1484 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - Running hbm2ddl schema export
1485 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - exporting generated schema to database
1571 [main] INFO org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete
Hibernate: insert into Klient (id, imie, nazwisko) values (default, ?, ?)
Hibernate: values identity_val_local()
BUILD SUCCESSFUL (total time: 3 seconds)

Tym razem wszystko działa jak należy. Można zajrzeć do bazy, aby upewnić się, że rekord z danymi klienta został faktycznie założony w bazie. Pozostawiam to wytrwałemu czytelnikowi jako zadanie domowe. Powodzenia!

Osobiste