Spring与JDBC,事务管理

来源:互联网 发布:linux退出vim进入末行 编辑:程序博客网 时间:2024/04/29 14:04

Spring与JDBC,事务管理

Spring+JDBC组合开发

  • 配置数据源(c3p0)

使用c3p0连接池,需要先把c3p0的jar包添加到工程中。我们在配置时把数据库连接信息放到外面单独的jdbc.properties文件中。

<!-- 使用外部的properties配置文件 --><context:property-placeholder location="classpath:jdbc.properties" /><!-- 定义c3p0数据源 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><!-- 数据库连接信息 --><property name="jdbcUrl" value="${jdbcUrl}"></property><property name="driverClass" value="${driverClass}"></property><property name="user" value="${username}"></property><property name="password" value="${password}"></property><!-- 其他配置 --><!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 --><property name="initialPoolSize" value="3"></property><!--连接池中保留的最小连接数。Default: 3 --><property name="minPoolSize" value="3"></property><!--连接池中保留的最大连接数。Default: 15 --><property name="maxPoolSize" value="5"></property><!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --><property name="acquireIncrement" value="3"></property><!--最大空闲时间,1800秒内未使用则连接被丢弃,若为0则永不丢弃。Default: 0 --><property name="maxIdleTime" value="1800"></property></bean>

jdbc.properties:

jdbcUrl = jdbc:mysql://localhost:3306/jdbcdriverClass = com.mysql.jdbc.Driverusername = rootpassword = 1234
  • 配置JdbcTemplate

JdbcTemplate是线程安全的,所以可以使用单例的模式。

<!-- 定义JdbcTemplate --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean>

使用JdbcTemplate可以方便JDBC开发,他使用了“模板方法模式”与“回调接口”的技巧。

  • JdbcTemplate的execute(..)方法
public void addUser(final User user) {jdbcTemplate.execute(new ConnectionCallback() {public Object doInConnection(Connection con) throws SQLException, DataAccessException {String sql = "insert into t_user(name, age) values(?,?)";PreparedStatement ps = con.prepareStatement(sql);ps.setString(1, user.getName());ps.setInt(2, user.getAge());ps.execute();ps.close();return null;}});}
  • 使用JdbcTemplate做增删改操作
// insert操作public void addUser(final User user) {jdbcTemplate.update("insert into t_user(name, age) values(?,?)", new Object[] { user.getName(), user.getAge() }); // 有null值也没问题}// update操作public void updateUser(User user) {jdbcTemplate.update("update t_user set name=?, age=? where id=?", //new Object[] { user.getName(), user.getAge(), user.getId() });}// delete操作public void deleteUser(Integer id) {jdbcTemplate.update("delete from t_user where id=?", new Object[] { id });}
  • 使用JdbcTemplate做查询操作
// 查询一条记录public User queryById(final Integer id) {String sql = "select name,age from t_user where id=?";return (User)jdbcTemplate.queryForObject(sql, new Object[] {id}, new RowMapper() {public Object mapRow(ResultSet rs, int rowNum) throws SQLException {String name = rs.getString("name");int age = rs.getInt("age");return new User(id, name, age);}});}// 查询数据列表public List<User> queryAll() {String sql = "select id,name,age from t_user";return jdbcTemplate.query(sql, new RowMapper() {public Object mapRow(ResultSet rs, int rowNum) throws SQLException {Integer id = rs.getInt(1);String name = rs.getString(2);Integer age = rs.getInt(3);return new User(id, name, age);}});}// 查询记录总数量public int queryCount() {String sql = "select count(*) from t_user";return jdbcTemplate.queryForInt(sql);}

声明式事务管理

  • 步骤:
    1. 引入spring-aop相关的4个jar文件
    2. 引入aop名称空间 【XML配置方式需要引入】
    3. 引入tx名称空间 【事务方式必须引入】
  • xml方式实现
1. DeptDao.javapublic class DeptDao {// 容器注入JdbcTemplate对象private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {this.jdbcTemplate = jdbcTemplate;}public void save(Dept dept){String sql = "insert into t_dept (deptName) values(?)";jdbcTemplate.update(sql,dept.getDeptName());}}2. DeptServicepublic class DeptService {// 容器注入dao对象private DeptDao deptDao;public void setDeptDao(DeptDao deptDao) {this.deptDao = deptDao;}/* * 事务控制? */public void save(Dept dept){// 第一次调用deptDao.save(dept);int i = 1/0; // 异常: 整个Service.save()执行成功的要回滚// 第二次调用deptDao.save(dept);}}3. App 测试类@Testpublic void testApp() throws Exception {//容器对象ApplicationContext ac = new ClassPathXmlApplicationContext("cn/itcast/a_tx/bean.xml");// 模拟数据Dept dept = new Dept();dept.setDeptName("测试: 开发部");DeptService deptService = (DeptService) ac.getBean("deptService");deptService.save(dept);} 4. bean.xml  (Spring声明式事务管理配置)<?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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsd      http://www.springframework.org/schema/context         http://www.springframework.org/schema/context/spring-context.xsd         http://www.springframework.org/schema/aop         http://www.springframework.org/schema/aop/spring-aop.xsd         http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 1. 数据源对象: C3P0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property><property name="user" value="root"></property><property name="password" value="root"></property><property name="initialPoolSize" value="3"></property><property name="maxPoolSize" value="10"></property><property name="maxStatements" value="100"></property><property name="acquireIncrement" value="2"></property></bean><!-- 2. JdbcTemplate工具类实例 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- 3. dao实例 --><bean id="deptDao" class="cn.itcast.a_tx.DeptDao"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean> <!-- 4. service实例 --><bean id="deptService" class="cn.itcast.a_tx.DeptService"><property name="deptDao" ref="deptDao"></property></bean><!-- #############5. Spring声明式事务管理配置############### --><!-- 5.1 配置事务管理器类 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 5.2 配置事务增强(如果管理事务?) --><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="get*" read-only="true"/><tx:method name="find*" read-only="true"/><tx:method name="*" read-only="false"/></tx:attributes></tx:advice><!-- 5.3 Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 --><aop:config><aop:pointcut expression="execution(* cn.csx.a_tx.DeptService.*())" id="pt"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/></aop:config></beans>
  • 注解方式实现
Bean.xm<?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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"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.xsd      http://www.springframework.org/schema/context         http://www.springframework.org/schema/context/spring-context.xsd         http://www.springframework.org/schema/aop         http://www.springframework.org/schema/aop/spring-aop.xsd         http://www.springframework.org/schema/tx      http://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 1. 数据源对象: C3P0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql:///hib_demo"></property><property name="user" value="root"></property><property name="password" value="root"></property><property name="initialPoolSize" value="3"></property><property name="maxPoolSize" value="10"></property><property name="maxStatements" value="100"></property><property name="acquireIncrement" value="2"></property></bean><!-- 2. JdbcTemplate工具类实例 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"></property></bean><!-- 事务管理器类 --><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><!-- 开启注解扫描 --><context:component-scan base-package="cn.itcast.b_anno"></context:component-scan><!-- 注解方式实现事务: 指定注解方式实现事务 --><tx:annotation-driven transaction-manager="txManager"/></beans>     DeptService@Servicepublic class DeptService {@Resourceprivate DeptDao deptDao;/* * 事务控制? */@Transactionalpublic void save(Dept dept){deptDao.save(dept);int i = 1/0;deptDao.save(dept);}}
  • 事务属性
@Transactional(readOnly = false,  // 读写事务timeout = -1,       // 事务的超时时间不限制noRollbackFor = ArithmeticException.class,  // 遇到数学异常不回滚isolation = Isolation.DEFAULT,              // 事务的隔离级别,数据库的默认propagation = Propagation.REQUIRED// 事务的传播行为)public void save(Dept dept){deptDao.save(dept);int i = 1/0;deptDao.save(dept);}

事务传播行为:

  • Propagation.REQUIRED

指定当前的方法必须在事务的环境下执行; 如果当前运行的方法,已经存在事务, 就会加入当前的事务;

  • Propagation.REQUIRED_NEW
指定当前的方法必须在事务的环境下执行;
如果当前运行的方法,已经存在事务:  事务会挂起; 会始终开启一个新的事务,执行完后;  刚才挂起的事务才继续运行。
0 0
原创粉丝点击