Spring框架引人注目的重要因素之一是它全面的事务支持。Spring框架提供了一致的事务管理抽象。但是在使用Spring 事务管理之前,一定要注意对数据源(DataSource)的配置,否则有可能带来你不想看到的结果。
1. 对
iBATIS SQL Maps 2.x的配置:
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="WEB-INF/sqlmap-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<property name="configLocation" value="WEB-INF/sqlmap-config.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
除了上面的配置,在编写代码时,采用SqlMapClientTemplate 和 SqlMapClientDaoSupport进行封装:
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao { public Account getAccount(String email) throws DataAccessException { return (Account) getSqlMapClientTemplate().queryForObject("getAccountByEmail", email); } public void insertAccount(Account account) throws DataAccessException { getSqlMapClientTemplate().update("insertAccount", account); } }
SqlMapClientTemplate
还提供了一个通用的
execute
方法,将用户自定义的
SqlMapClientCallback
的实现作为参数。举例来说,这可以实现批量操作:
public class SqlMapAccountDao extends SqlMapClientDaoSupport implements AccountDao {
...
public void insertAccount(Account account) throws DataAccessException {
getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
executor.startBatch();
executor.update("insertAccount", account);
executor.update("insertAddress", account.getAddress());
executor.executeBatch();
}
});
}
}
2. 对于
JDBC的配置:
对于dataSource的配置,此处略去。
Connection conn = DataSourceUtils.getConnection(dataSource);
你也可以使用
JdbcTemplate等模板类替我们完成资源的创建以及释放工作,从而简化了我们对JDBC的使用。使用JdbcTemplate进行编码只需要根据明确定义的一组契约来实现回调接口。
PreparedStatementCreator
回调接口通过给定的Connection
创建一个PreparedStatement,包含SQL和任何相关的参数。CallableStatementCreateor
实现同样的处理,只不过它创建的是CallableStatement。RowCallbackHandler
接口则从数据集的每一行中提取值。
比如以下的执行语句:
import javax.sql.DataSource;
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAStatement {
private JdbcTemplate jt;
private DataSource dataSource;
public void doExecute() {
jt = new JdbcTemplate(dataSource);
jt.execute("create table mytable (id integer, name varchar(100))");
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
import org.springframework.jdbc.core.JdbcTemplate;
public class ExecuteAStatement {
private JdbcTemplate jt;
private DataSource dataSource;
public void doExecute() {
jt = new JdbcTemplate(dataSource);
jt.execute("create table mytable (id integer, name varchar(100))");
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
}
3. 对于
Hibernate的配置:
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean>
除了上面的配置,在编写代码时,采用HibernateTemplate对session进行封装:
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean>
除了上面的配置,在编写代码时,采用HibernateTemplate对session进行封装:
HibernateTemplate ht = new HibernateTemplate(sessionFactory);
return (Collection) ht.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery(
"from test.Product product where product.category=?");
query.setString(0, category);
return query.list();
}
});
return (Collection) ht.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery(
"from test.Product product where product.category=?");
query.setString(0, category);
return query.list();
}
});
一个回调实现能够有效地在任何Hibernate数据访问中使用。
HibernateTemplate
会确保当前Hibernate的
Session
对象的正确打开和关闭,并直接参与到事务管理中去。 Template实例不仅是线程安全的,同时它也是可重用的。因而他们可以作为外部对象的实例变量而被持有。对于那些简单的诸如find、load、saveOrUpdate或者delete操作的调用,
HibernateTemplate
提供可选择的快捷函数来替换这种回调的实现。 不仅如此,Spring还提供了一个简便的
HibernateDaoSupport
基类,这个类提供了
setSessionFactory(..)
方法来接受一个
SessionFactory
对象,同时提供了
getSessionFactory()
和
getHibernateTemplate()
方法给子类使用。 综合了这些,对于那些典型的业务需求,就有了一个非常简单的DAO实现:
public class ProductDaoImpl extends HibernateDaoSupport implements ProductDao {
public Collection loadProductsByCategory(String category) throws DataAccessException
{
return getHibernateTemplate().find( "from test.Product product where product.category=?", category);
}
}