1,Data access with JDBC
使用springJdbc非常简单。在我们写daoImpl的时候只需要继承spring的org.springframework.jdbc.core.support.JdbcDaoSupport该类。在实现以下需要实现的接口即可,再在需要实现的接口方法中使用通过继承JdbcDaoSupport类的jdbcTemplate对象的update、execute、query等方法完成我们需要的方法即可。
比如我们要写一个UserDaoImpl类泽代码如下:
package com.xiaohui.jdbc; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.PreparedStatementCallback; import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.support.JdbcDaoSupport; public class UserDaoImpl extends JdbcDaoSupport implements IUserDao { @Override public void save(User u) { String sql = "INSERT INTO user VALUES(NULL,?)"; this.getJdbcTemplate().update(sql, u.getName()); } @Override public void update(User u) { String sql = "UPDATE user SET name =? WHERE id=?"; this.getJdbcTemplate().update(sql, u.getName(), u.getId()); } @Override public void delete(Long id) { this.getJdbcTemplate().execute("delete from user where id=" + id); } @Override public List<User> list() { String sql = "SELECT * FROM user"; List<User> users = this.getJdbcTemplate().query(sql, new ResultSetExtractor<List<User>>() { @Override public List<User> extractData(ResultSet rs) throws SQLException, DataAccessException { List<User> userList = new ArrayList<User>(); while (rs.next()) { User user = new User(); user.setId(rs.getLong("id")); user.setName(rs.getString("name")); userList.add(user); } return userList; } }); return users; } @Override public User getById(final Long id) { String sql = "select * from user where id=?"; User u = this.getJdbcTemplate().execute(sql, new PreparedStatementCallback<User>() { @Override public User doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException { ps.setLong(1, id); ResultSet set = ps.executeQuery(); while (set.next()) { User u = new User(); u.setId(id); u.setName(set.getString("name")); return u; } return null; } }); return u; } }
同时我们需要给属性jdbcTemplate在xml中配置属性值xml如下:需要在source folder目录下创建一个jdbc.properties。<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="template" class="org.springframework.jdbc.core.JdbcTemplate" scope="prototype"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="userdao" class="com.xiaohui.jdbc.UserDaoImpl"> <property name="jdbcTemplate" ref="template"/> </bean> </beans>
这样我们就可以通过获取userdao 来与数据库交互了。
2,spring事务管理
事务是一组操作的执行单元,相对于数据库操作来讲,事务管理的是一组SQL指令,比如增加,修改,删除等,事务的一致性,要求,这个事务内的操作必须全部执行成功,如果在此过程种出现了差错,比如有一条SQL语句没有执行成功,那么这一组操作都将全部回滚。事务特性:
atomic(原子性):要么都发生,要么都不发生。 consistent(一致性):数据应该不被破坏。 solate(隔离性):用户间操作不相混淆。 Durable(持久性):永久保存,例如保存到数据库中等。spring提供的两种事务管理方式 基于xml的事务管理和基于aop注解的管理事务。在spring中spring没有直接管理事务,而是将管理事务的责任委托给JTA或相应的持久性机制所提供的某个特定平台的事务实现
事务管理器实现 目标 org.springframework.jdbc.datasource.DataSourceTransactionManager 在单一的JDBC Datasource中的管理事务 org.springframework.orm.hibernate3.HibernateTransactionManager 当持久化机制是hibernate时,用它来管理事务 org.springframework.jdo.JdoTransactionManager 当持久化机制是Jdo时,用它来管理事务。 org.springframework.transaction.jta.JtaTransactionManager 使用一个JTA实现来管理事务。在一个事务跨越多个资源时必须使用 org.springframework.orm.ojb.PersistenceBrokerTransactionManager 当apache的ojb用作持久化机制时,用它来管理事务。
理解事务属性--事物传播规则
REQUIRED :业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务 NOT_SUPPORTED :声明方法不需要事务。如果方法没有关联到一个事务,容器不会为它开启事务。如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行 REQUIRESNEW:属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法执行结束,新事务才算结束,原先的事务才会恢复执行 MANDATORY:该属性指定业务方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果业务方法在没有事务的环境下调用,容器就会抛出例外 SUPPORTS:这一事务属性表明,如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分。如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行 Never:指定业务方法绝对不能在事务范围内执行。如果业务方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,才能正常执行 NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效1,基于注解的方式管理事务。
基于注解的使用比较简单,只要在xml中引入tx命名空间,并配置事务管理器transactionManager xml如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-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"> <!-- springJdbc --> <context:property-placeholder location="jdbc.properties" /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" > <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="accDao" class="com.xiaohui.trans.AccountDaoImpl"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="accountService" class="com.xiaohui.trans.AccountServiceImpl"> <property name="dao" ref="accDao"></property> </bean> </beans>这时在业务层需要开启事务的方法上面加上@Transactional注解即可。
@Transactional public void trans(Account accIn, Account accOut, Double amount) { // 转出金额 dao.transOut(accOut, amount); // 转入金额 dao.transIn(accIn, amount); }
如上则在转账的过程里出现任何异常事物会回滚,都不会影响到数据库底层数据的。2,基于xml配置的事务管理
使用xml配置管理事务,我们同样需要告诉spring容器,我们使用具体的什么管理器,jdbc的还是hibernate的,所以还需要配置transactionManager,这次我们需要使用aop来管理我们的事物。
这次我们需要加入aop的命名空间,再将上面的
<tx:annotation-driven transaction-manager="transactionManager" />xml代码替换为:
<aop:config> <aop:pointcut expression="execution(* com.xiaohui.trans.*ServiceImpl.*(..))" id="pointcut"/> <aop:advisor advice-ref="transAdvice" pointcut-ref="pointcut"/> </aop:config> <tx:advice id="transAdvice"> <tx:attributes> <tx:method name="trans"/> <tx:method name="transIn" propagation="REQUIRED"/> <tx:method name="transOut" propagation="REQUIRED"/> </tx:attributes> </tx:advice>即可。