java - Minimal Hibernate 4 XML configuration with Spring 3 for annotation based transaction management and object mapping? -
assuming i've got working spring project minimal amount of configuration needed add in hibernate 4 spring 3 xml configuration? want use annotation based transaction management , have objects mapped using annotations.
note: self-answer q&a style question intended give canonical answer common problem. intend expand question on time keep date hibernate.
i find using hibernate spring's xml config intuitive, if you've never added project before, can pain working correctly. using spring's xml config preferred option hibernate 4.
so you've set spring project , got working. want add hibernate.
i configure hibernate in separate xml file called database-servlet.xml
inside web-inf directory, name doesn't matter long on classpath.
my new database-servlet.xml
looks this:
<?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:jdbc="http://www.springframework.org/schema/jdbc" 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.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd"> </beans>
you'll notice imported tx
, jdbc
spring namespaces. because going use them quite heavily in config file.
first thing want enable annotation based transaction management (@transactional
). main reason people use hibernate in spring because spring manage transactions you. add following line configuration file:
<tx:annotation-driven />
we need create data source. data source database hibernate going use persist objects. 1 transaction manager have 1 data source. if want hibernate talk multiple data sources have multiple transaction managers.
the type of data source depend on want accomplish. can specify existing database, or can create new in-memory hsql/derby/h2 database comes prepackaged spring. have existing database hibernate connects when deploy project physical testing, use in-memory database unit/integration testing.
i'll show how create in-memory database first.
<jdbc:embedded-database id="datasource" type="hsql"> <jdbc:script location="classpath:/setup.sql" /> . . . <!-- many scripts can run --> </jdbc:embedded-database>
the above config, create embedded (in-memory) hsql database bean, run script setup.sql
, make datasource
bean available application context. don't have specify database type
hsql default, clear. setup.sql can located anywhere within classpath (web-inf directory usually). can specify many sql scripts like. can set if should run on creation or destruction of database.
this database live , die application. do not use embedded database on production project, 1 power outage, , data gone.
to connect data source existing database configuration different.
<bean id="datasource" class="org.springframework.jdbc.datasource.drivermanagerdatasource"> <property name="driverclassname" value="" /> <property name="url" value="" /> <property name="username" value="" /> <property name="password" value="" /> </bean>
the class of bean can implements (i think) javax.sql.datasource
write own. example class provided spring, doesn't have own thread pool. popular alternative apache commons org.apache.commons.dbcp.basicdatasource
, there many others. i'll explain each of properties below:
driverclassname: path jdbc driver. database specific jar should available on classpath. ensure have date version. if using oracle database, you'll need oracledriver. if have mysql database, you'll need mysqldriver. see if can find driver need here quick google should give correct driver.
url: url database.
jdbc\:oracle\:thin\:\path\to\your\database
orjdbc:mysql://path/to/your/database
. if google around default location of database using, should able find out should be. if gettinghibernateexception
messageorg.hibernate.hibernateexception: connection cannot null when 'hibernate.dialect' not set
, following guide, there 90% chance url wrong, 5% chance database isn't started , 5% chance username/password wrong.username: username use when authenticating database.
password: password use when authenticating database.
the next thing, set sessionfactory
. thing hibernate uses create , manage transactions, , talks database. has quite few configuration options try explain below.
<bean id="sessionfactory" class="org.springframework.orm.hibernate4.localsessionfactorybean"> <property name="datasource" ref="datasource" /> <property name="packagestoscan" value="au.com.project /> <property name="hibernateproperties"> <props> <prop key="hibernate.use_sql_comments">true</prop> <prop key="hibernate.hbm2ddl.auto">validate</prop> </props> </property> </bean>
datasource: data source bean. if changed id of datasource, set here.
packagestoscan: packages scan find jpa annotated objects. these objects session factory needs manage, pojo's , annotated
@entity
. more information on how set object relationships in hibernate see here.annotatedclasses (not shown): can provide list of classes hibernate scan if not in same package. should use either
packagestoscan
orannotatedclasses
not both. declaration looks this:
<property name="annotatedclasses"> <list> <value>foo.bar.package.model.person</value> <value>foo.bar.package.model.thing</value> </list> </property>
- hibernateproperties: there myriad of these lovingly documented here. main ones using follows:
- hibernate.hbm2ddl.auto: 1 of hottest hibernate questions details property. see more info. use validate, , set database using either sql scripts (for in-memory), or create database beforehand (existing database).
- hibernate.show_sql: boolean flag, if true hibernate print sql generates
stdout
. can configure logger show values being bound queries settinglog4j.logger.org.hibernate.type=trace
log4j.logger.org.hibernate.sql=debug
in log manager (i use log4j). - hibernate.format_sql: boolean flag, cause hibernate pretty print sql stdout.
- hibernate.dialect (not shown, reason): lot of old tutorials out there show how set hibernate dialect use communicate database. hibernate can auto-detect dialect use based on jdbc driver using. since there 3 different oracle dialects , 5 different mysql dialects, i'd leave decision hibernate. full list of dialects hibernate supports see here.
the last 2 beans need declare are:
<bean class="org.springframework.dao.annotation.persistenceexceptiontranslationpostprocessor" id="persistenceexceptiontranslator" /> <bean id="transactionmanager" class="org.springframework.orm.hibernate4.hibernatetransactionmanager"> <property name="sessionfactory" ref="sessionfactory" /> </bean>
the persistenceexceptiontranslator
translates database specific hibernateexception
or sqlexceptions
spring exceptions can understood application context.
the transactionmanager
bean controls transactions roll-backs.
note: should autowiring sessionfactory
bean dao's.
once you've done this. have add new database-servlet.xml
web.xml file.
<context-param> <param-name>contextconfiglocation</param-name> <param-value> /web-inf/database-servlet.xml . . . </param-value> </context-param>
this should need hibernate working. still need add annotations objects, , add @transactional
service layer methods interact dao.
handy hint: if using dependency manager ivy or maven, , pull in spring & hibernate javadocs, can view them in sts xml editor hovering on properties.
how works in practice
in service class, when annotate method @transactional
, call method elsewhere few things happen. hibernate transactionmanager
uses aop pointcut inject code before method gets invoked. transactionmanager
following things (in no particular order):
attempts ascertain persistent objects (that knows about) in memory.
check
sessionfactory
existing transactional session, , usesessionfactory
create new 1 if 1 doesn't exist, depending on parameters inside annotation.
from point transaction manager records changes make persistent objects discovered, queries run through current session. if exception thrown, simple matter roll has occurred since method invoked.
the sessionfactory
bean responsible creating, maintaining, closing , flushing database sessions transactionmanager
asks create. that's why autowire sessionfactory
dao's , make run queries through it.
one of biggest questions new hibernate users ask "when changes committed?" , answer makes sense when think how transactionmanager
works sesisonfactory
. database changes flushed , committed when exit service method annotated @transactional
. reason is, transaction supposed represent single 'unit' of unbroken work. if goes wrong unit, assumed unit failed , changes should rolled back. sessionfactory
flush , clear session when exit service method called originally.
that's not won't flush , clear session while transaction going on. example, if call service method add collection of 5 objects , return total count of objects in database, sessionfactory
realise query (select count(*)
) requires updated state accurate, , flush addition of 5 objects before running count query. execution this:
//service @override @transactional public long saveandcount(list<foo> listoffoo){ for(foo foo : listoffoo){ //doesn't instantly saved database. foodao.saveorupdate(foo); } /* * before actual select count(*) query run, sessionfactory * flush save operation of 5 foo objects. */ return foodao.count(); }
to clear, dao have no session management code @ all. have along lines of sessionfactory.getcurrentsession().buildcriteria(foo.class);
, that's it. no manipulating instances of session
object, no calls flush()
or clear()
. that's beauty of using hibernate spring.
disclaimer: not know if these examples work standalone hibernate
i not in way affiliated hibernate or hibernate dev team. i'm providing these examples have reference point when i'm answering questions on hibernate tag. these examples , discussions based on own opinion how develop applications using hibernate. these examples in no way comprehensive. i'm basing them on common situations i've used hibernate in past.
if encounter issues trying implement these examples, not comment , expect me fix problem. part of learning hibernate learning in's , out 's of api. if there mistake examples, please feel free edit them.
Comments
Post a Comment