刚好十一期间 Spring2.0的中文reference出来了 所以把这部分总结实践一下
一 资源管理
DataSource sessionFactory的组装
beans-config.xml
<?
xmlversion="1.0"encoding="UTF-8"
?>
<!
DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http://www.springframework.org/dtd/spring-beans.dtd"
>
<
beans
>
<!--
===================================================================
-->
<!--
JDBCdataSource
-->
<!--
===================================================================
-->
<!--
***********************************************************************
<beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<propertyname="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<propertyname="url">
<value>jdbc:mysql://localhost:3306/shtest</value>
</property>
<propertyname="username">
<value>root</value>
</property>
<propertyname="password">
<value>72001234</value>
</property>
</bean>
************************************************************************
-->
<!--
===================================================================
-->
<!--
c3p0dataSource
-->
<!--
===================================================================
-->
<
bean
id
="dataSource"
class
="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method
="close"
>
<
property
name
="driverClass"
>
<
value
>
com.mysql.jdbc.Driver
</
value
>
</
property
>
<
property
name
="jdbcUrl"
>
<
value
>
jdbc:mysql://localhost:3306/shtest
</
value
>
</
property
>
<
property
name
="properties"
>
<
props
>
<
prop
key
="c3p0.acquire_increment"
>
2
</
prop
>
<
prop
key
="c3p0.idle_test_period"
>
200
</
prop
>
<
prop
key
="c3p0.timeout"
>
1000
</
prop
>
<
prop
key
="c3p0.max_size"
>
100
</
prop
>
<
prop
key
="hibernate.c3p0.max_statements"
>
100
</
prop
>
<
prop
key
="hibernate.c3p0.min_size"
>
20
</
prop
>
<
prop
key
="user"
>
root
</
prop
>
<
prop
key
="password"
>
72001234
</
prop
>
</
props
>
</
property
>
</
bean
>
<!--
===================================================================
-->
<!--
HibernatesessionFactory
-->
<!--
===================================================================
-->
<
bean
id
="sessionFactory"
class
="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
destroy-method
="close"
>
<
property
name
="dataSource"
>
<
ref
bean
="dataSource"
/>
</
property
>
<
property
name
="mappingResources"
>
<
list
>
<
value
>
/com/ergal/hibernate/User.hbm.xml
</
value
>
</
list
>
</
property
>
<
property
name
="hibernateProperties"
>
<
props
>
<
prop
key
="hibernate.dialect"
>
org.hibernate.dialect.MySQLDialect
</
prop
>
<
prop
key
="hibernate.show_sql"
>
true
</
prop
>
<
prop
key
="hibernate.current_session_context_class"
>
thread
</
prop
>
</
props
>
</
property
>
</
bean
>
<!--
===================================================================
-->
<!--
HibernatePOJO
-->
<!--
===================================================================
-->
<
bean
id
="userDao"
class
="com.ergal.hibernate.UserDao"
>
<
property
name
="sessionFactory"
>
<
ref
bean
="sessionFactory"
/>
</
property
>
</
bean
>
<!--
===================================================================
-->
<!--
transactionManager
-->
<!--
===================================================================
-->
<
bean
id
="transactionManager"
class
="org.springframework.orm.hibernate3.HibernateTransactionManager"
>
<
property
name
="sessionFactory"
>
<
ref
bean
="sessionFactory"
/>
</
property
>
</
bean
>
<!--
===================================================================
-->
<!--
DaoProxy
-->
<!--
===================================================================
-->
<
bean
id
="userDaoProxy"
class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
<
property
name
="transactionManager"
>
<
ref
bean
="transactionManager"
/>
</
property
>
<
property
name
="proxyInterfaces"
>
<
list
>
<
value
>
com.ergal.hibernate.IUserDao
</
value
>
</
list
>
</
property
>
<
property
name
="target"
>
<
ref
bean
="userDao"
/>
</
property
>
<
property
name
="transactionAttributes"
>
<
props
>
<
prop
key
="insert"
>
PROPAGATION_REQUIRED
</
prop
>
</
props
>
</
property
>
</
bean
>
</
beans
>
也可以直接使用JNDI资源
<
beans
>
<
bean
id
="myDataSource"
class
="org.springframework.jndi.JndiObjectFactoryBean"
>
<
property
name
="jndiName"
value
="java:comp/env/jdbc/myds"
/>
</
bean
>
...
</
beans
>
二 HibernateTemplate
HibernateTemplate上有一些方便的方法可以自动建立callback对象 一些方法get() save() delete() 等等
在不使用代理的情况下
UserDao变的比较灵活
比如按名字查询的方法可以写成
package
com.ergal.hibernate;
import
java.util.Iterator;
import
java.util.List;
import
org.hibernate.Hibernate;
import
org.hibernate.Session;
import
org.hibernate.SessionFactory;
import
org.hibernate.Transaction;
import
org.springframework.orm.hibernate3.HibernateTemplate;
public
class
UserDao
implements
IUserDao
...
{
privateHibernateTemplatehibernateTemplate;
publicUserDao()...{}
/**//*
publicUserDao(SessionFactorysessionFactory)
{
this.sessionFactory=sessionFactory;
}*/
publicvoidsetSessionFactory(SessionFactorysessionFactory)
...{
hibernateTemplate=newHibernateTemplate(sessionFactory);
}
publicvoidinsert(Useruser)
...{
hibernateTemplate.save(user);
//TODOAuto-generatedmethodstub
/**//*Sessionsession=sessionFactory.openSession();
Transactiontx=session.beginTransaction();
session.save(user);
tx.commit();
session.close();*/
}
publicStringgetPassword(Stringusername)
...{
/**//*
Sessionsession=sessionFactory.openSession();
Transactiontx=session.beginTransaction();
Listresult=session.createQuery("fromUseruwhereusername=:name").setString("name",username).list();
Stringpassword=null;
for(Iteratorit=result.iterator();it.hasNext();)
{
Useru=(User)it.next();
Hibernate.initialize(u.getPassword());
password=(String)u.getPassword();
}
tx.commit();
session.close();
returnpassword;
*/
Listresult=hibernateTemplate.find("fromUseruwhereusername=?",username);
Stringpassword=null;
for(Iteratorit=result.iterator();it.hasNext();)
...{
Useru=(User)it.next();
Hibernate.initialize(u.getPassword());
password=(String)u.getPassword();
}
returnpassword;
}
}
也可以写成
SessionFactorysf
=
hibernateTemplate.getSessionFactory();
Sessionsession
=
sf.openSession();
Transactiontx
=
session.beginTransaction();
Listresult
=
session.createQuery(
"
fromUseruwhereusername=:name
"
).setString(
"
name
"
,username).list();
Stringpassword
=
null
;
for
(Iteratorit
=
result.iterator();it.hasNext();)
...
{
Useru=(User)it.next();
Hibernate.initialize(u.getPassword());
password=(String)u.getPassword();
}
return
password;
当然 直接利用hibernateTemplate的方法是比较简洁的
三 HibernateDaoSupport
可以省去一些SessionFactory和HibernateTemplate的管理 只需要注入SessionFactory的实例就可以了
<!-- ======== CONSTRUCTOR SUMMARY ======== --><!-- -->
Constructor Summary
<!-- ========== METHOD SUMMARY =========== -->
<!-- -->
Method Summary
protected void |
checkDaoConfig() Abstract subclasses must override this to check their configuration. |
protected void |
closeSessionIfNecessary(org.hibernate.Sessionsession) Deprecated.in favor of releaseSession |
protected DataAccessException |
convertHibernateAccessException(org.hibernate.HibernateExceptionex) Convert the given HibernateException to an appropriate exception from the org.springframework.dao hierarchy. |
protected HibernateTemplate |
createHibernateTemplate(org.hibernate.SessionFactorysessionFactory) Create a HibernateTemplate for the given SessionFactory. |
HibernateTemplate |
getHibernateTemplate() Return the HibernateTemplate for this DAO, pre-initialized with the SessionFactory or set explicitly. |
protected org.hibernate.Session |
getSession() Get a Hibernate Session, either from the current transaction or a new one. |
protected org.hibernate.Session |
getSession(booleanallowCreate) Get a Hibernate Session, either from the current transaction or a new one. |
org.hibernate.SessionFactory |
getSessionFactory() Return the Hibernate SessionFactory used by this DAO. |
protected void |
releaseSession(org.hibernate.Sessionsession) Close the given Hibernate Session, created via this DAO's SessionFactory, if it isn't bound to the thread. |
void |
setHibernateTemplate(HibernateTemplatehibernateTemplate) Set the HibernateTemplate for this DAO explicitly, as an alternative to specifying a SessionFactory. |
void |
setSessionFactory(org.hibernate.SessionFactorysessionFactory) Set the Hibernate SessionFactory to be used by this DAO. |
<!-- -->
于是可以把代码改成以下来测试一下
package
com.ergal.hibernate;
import
java.util.Iterator;
import
java.util.List;
import
org.hibernate.Hibernate;
import
org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public
class
UserDao
extends
HibernateDaoSupport
implements
IUserDao
...
{
//privateHibernateTemplatehibernateTemplate;
publicUserDao()...{}
/**//*
publicUserDao(SessionFactorysessionFactory)
{
this.sessionFactory=sessionFactory;
}*/
/**//*
publicvoidsetSessionFactory(SessionFactorysessionFactory)
{
hibernateTemplate=newHibernateTemplate(sessionFactory);
}*/
publicvoidinsert(Useruser)
...{
getHibernateTemplate().save(user);
//TODOAuto-generatedmethodstub
/**//*Sessionsession=sessionFactory.openSession();
Transactiontx=session.beginTransaction();
session.save(user);
tx.commit();
session.close();*/
}
publicStringgetPassword(Stringusername)
...{
/**//*
Sessionsession=sessionFactory.openSession();
Transactiontx=session.beginTransaction();
Listresult=session.createQuery("fromUseruwhereusername=:name").setString("name",username).list();
Stringpassword=null;
for(Iteratorit=result.iterator();it.hasNext();)
{
Useru=(User)it.next();
Hibernate.initialize(u.getPassword());
password=(String)u.getPassword();
}
tx.commit();
session.close();
returnpassword;
*/
Listresult=getHibernateTemplate().find("fromUseruwhereusername=?",username);
Stringpassword=null;
for(Iteratorit=result.iterator();it.hasNext();)
...{
Useru=(User)it.next();
password=(String)u.getPassword();
}
returnpassword;
}
}
这样很多管理就被省去了 包括session sessionFactory
reference上还写了一些关于使用
Hibernate原生API的方法
就是直接自己编写Hibernate的实现方法来实现DAO
如
Sessionsession
=
sessionFactory.openSession();
Transactiontx
=
session.beginTransaction();
Listresult
=
session.createQuery(
"
fromUseruwhereusername=:name
"
).setString(
"
name
"
,username).list();
Stringpassword
=
null
;
for
(Iteratorit
=
result.iterator();it.hasNext();)
...
{
Useru=(User)it.next();
Hibernate.initialize(u.getPassword());
password=(String)u.getPassword();
}
tx.commit();
session.close();
return
password;
不使用回调基于DAO的实现
无需将Hibernate访问代码放在一个回调中 只要符合Spring通用的DataAccessException异常体系HibernateDaoSupport提供了访问当前事务绑定的session对象的函数 保证在这种情况下异常的正常转化 (false)作为参数 表示是否允许创建 此时整个调用在一个session中完成(整个生命周期由事务控制 避免了关闭session的需要)
......
Sessionsession
=
getSession(getSessionFactory,
false
)
try
...
{
Listresult=session.createQuery("fromUseruwhereusername=:name").setString("name",username).list();
if(result==null)
...{
throw.....
}
returnresult;
}
catch
(HibernateExceptionex)
...
{
throwconvetHibernateAccessException(ex);
}
编程式事务管理
自己组装业务实现的类 利用
org.springframework.transaction.support .TransactionTemplate
org.springframework.transaction.support.TransactionCallbackWithoutResult
org.springframework.orm.hibernate3.HibernateTemplate
org.springframework.transaction.TransactionStatus
org.springframework.orm.hibernate3.HibernateTransactionManager
org.springframework.transaction.TranscationDefinition
这些接口和方法来进行事务管理 看起来没有那么简洁
声明式事务管理
定义一个代理类
核心部分如下
<!--
===================================================================
-->
<!--
transactionManager
-->
<!--
===================================================================
-->
<
bean
id
="transactionManager"
class
="org.springframework.orm.hibernate3.HibernateTransactionManager"
>
<
property
name
="sessionFactory"
>
<
ref
bean
="sessionFactory"
/>
</
property
>
</
bean
>
<!--
===================================================================
-->
<!--
DaoProxy
-->
<!--
===================================================================
-->
<
bean
id
="userDaoProxy"
class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
>
<
property
name
="transactionManager"
>
<
ref
bean
="transactionManager"
/>
</
property
>
<
property
name
="proxyInterfaces"
>
<
list
>
<
value
>
com.ergal.hibernate.IUserDao
</
value
>
</
list
>
</
property
>
<
property
name
="target"
>
<
ref
bean
="userDao"
/>
</
property
>
<
property
name
="transactionAttributes"
>
<
props
>
<
prop
key
="insert"
>
PROPAGATION_REQUIRED
</
prop
>
</
props
>
</
property
>
</
bean
>