Spring入门笔记(三)之JdbcTemplate和事务管理

来源:互联网 发布:面具淘宝 编辑:程序博客网 时间:2024/05/01 06:16

  Craig Walls所著《Spring实战》一书里说,Spring的两大关键字:DI(依赖注入),AOP(面向切面编程)。在之前的两篇博客里,我们已经学习了spring的核心,DI和AOP。大头我们已经学完了,这篇博客主要是介绍剩下的一些知识点,如JdbcTemplate和事务管理等。

JdbcTemplate

  • spring 提供用于操作JDBC工具类,类似:DBUtils。
  • 依赖 连接池DataSource (数据源)

1.1环境搭建

创建表(我这里使用的是MySql)

USE test;CREATE TABLE t_user(  id INT PRIMARY KEY AUTO_INCREMENT,  username VARCHAR(50),  PASSWORD VARCHAR(32));INSERT INTO t_user(username,PASSWORD) VALUES('jack','1234');INSERT INTO t_user(username,PASSWORD) VALUES('rose','5678');

导入Jar包


1.2使用API

public class TestApi {public static void main(String[] args) {//1 创建数据源(连接池) dbcpBasicDataSource dataSource = new BasicDataSource();// * 基本4项dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/test");dataSource.setUsername("root");dataSource.setPassword("root");//2  创建模板JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);//3 通过api操作jdbcTemplate.update("insert into t_user(username,password) values(?,?);", "tom","998");}}

dao类:

public class UserDao {//JDBC模板将有spring注入private JdbcTemplate jdbcTemplate;public void setJdbcTemplate(JdbcTemplate jdbcTemplate){this.jdbcTemplate = jdbcTemplate;}public void update(User user){String sql = "update t_user set username=?,password=? where id=?";Object[] args = {user.getUsername(),user.getPassword(),user.getId()};jdbcTemplate.update(sql,args);}}



1.3配置DBCP示例:

<?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:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop"       xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans.xsd          http://www.springframework.org/schema/aop           http://www.springframework.org/schema/aop/spring-aop.xsd          http://www.springframework.org/schema/context           http://www.springframework.org/schema/context/spring-context.xsd"><!-- 创建数据源 --><bean id="dataSourceId" class="org.apache.commons.dbcp.BasicDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/test"></property><property name="username" value="root"></property><property name="password" value="root"></property></bean><!-- 创建模板 ,需要注入数据源--><bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSourceId"></property></bean><!-- 配置dao --><bean id="userDaoId" class="com.spring.dbcp.UserDao"><property name="jdbcTemplate" ref="jdbcTemplateId"></property></bean></beans>

1.4 C3P0配置示例

<!-- 创建数据源 c3p0--><bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="com.mysql.jdbc.Driver"></property><property name="jdbcUrl" value="jdbc:mysql://localhost:3306/<span style="font-family:SimSun;">test</span>"></property><property name="user" value="root"></property><property name="password" value="1234"></property></bean>

1.5使用JdbcDaoSupport

   为了简化dao类,每次注入JdbcTemplate,我们可以继承JdbcDaoSupport,替代set方法。

public class UserDao extends JdbcDaoSupport{public void update(User user){String sql = "update t_user set username=?,password=? where id=?";Object[] args = {user.getUsername(),user.getPassword(),user.getId()};this.getJdbcTemplate().update(sql,args);}}

<!-- 配置dao * dao 继承 JdbcDaoSupport,之后只需要注入数据源,底层将自动创建模板--><bean id="userDaoId" class="com.spring.jdbcSupport.UserDao"><property name="dataSource" ref="dataSourceId"></property></bean>

源码分析:



1.6配置Properties

properties文件:

jdbc.driverClass=com.mysql.jdbc.Driverjdbc.jdbcUrl=jdbc:mysql://localhost:3306/<span style="font-family:SimSun;">test</span>jdbc.user=rootjdbc.password=1234

Spring配置文件

<!-- 加载配置文件 "classpath:"前缀表示 src下在配置文件之后通过  ${key} 获得内容--><context:property-placeholder location="classpath:com/spring/properties/jdbcInfo.properties"/><!-- 创建数据源 c3p0--><bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driverClass}"></property><property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property><property name="user" value="${jdbc.user}"></property><property name="password"  value="${jdbc.password}"></property></bean>

2.事务管理

2.1回顾事务

  • 事务:一组业务操作ABCD,要么全部成功,要么全部不成功。
  • 特性:ACID

   原子性:整体

            一致性:完成

            隔离性:并发

            持久性:结果

  • 隔离问题:

     脏读:一个事务读到另一个事务没有提交的数据

  不可重复读:一个事务读到另一个事务已提交的数据(update

  虚读(幻读):一个事务读到另一个事务已提交的数据(insert

  • 隔离级别:

   read uncommitted:读未提交。存在3个问题

   read committed:读已提交。解决脏读,存在2个问题

   repeatable read:可重复读。解决:脏读、不可重复读,存在1个问题。

   serializable :串行化。都解决,单事务。


  • mysql 事务操作--简单,示例描述:
ABCD 一个事务Connection conn = null;try{  //1 获得连接  conn = ...;  //2 开启事务  conn.setAutoCommit(false);  A  B  C  D  //3 提交事务  conn.commit();} catche(){  //4 回滚事务  conn.rollback();}


  •  mysql 事务操作--Savepoint  示例描述:
需求:AB(必须),CD(可选) Connection conn = null;Savepoint savepoint = null;  //保存点,记录操作的当前位置,之后可以回滚到指定的位置。(可以回滚一部分)try{  //1 获得连接  conn = ...;  //2 开启事务  conn.setAutoCommit(false);  A  B  savepoint = conn.setSavepoint();  C  D  //3 提交事务  conn.commit();} catche(){  if(savepoint != null){   //CD异常     // 回滚到CD之前     conn.rollback(savepoint);     // 提交AB     conn.commit();  } else{   //AB异常     // 回滚AB     conn.rollback();  }}

2.2事务管理介绍

导入Jar包:

transaction  -->  tx


在开始具体实现之前,我们必须先了解三个顶级接口



  • PlatformTransactionManager  平台事务管理器,spring要管理事务,必须使用事务管理器

   进行事务配置时,必须配置事务管理器

  • TransactionDefinition:事务详情(事务定义、事务属性),spring用于确定事务具体详情,

   例如:隔离级别、是否只读、超时时间

   进行事务配置时,必须配置详情spring将配置项封装到该对象实例。

  • TransactionStatus:事务状态,spring用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。

   spring底层根据状态进行相应操作。


2.2.1 PlatformTransactionManager事务管理器

  • 导入jar包:需要时平台事务管理器的实现类


  • 常见的事务管理器

   DataSourceTransactionManagerjdbc开发时事务管理器,采用JdbcTemplate

   HibernateTransactionManager,hibernate开发时事务管理器,整合hibernate


  •  api详解

    TransactionStatus getTransaction(TransactionDefinition definition),事务管理器 通过“事务详情”,获得“事务状态”,从而管理事务。

    void commit(TransactionStatus status)  根据状态提交

    void rollback(TransactionStatus status) 根据状态回滚


2.2.2 TransactionStatus(了解即可)



2.2.3 TransactionDefinition


  • 传播行为:在两个业务之间如何共享事务。

PROPAGATION_REQUIRED , required , 必须  【默认值】

           支持当前事务,A如果有事务,B将使用该事务。

           如果A没有事务,B将创建一个新的事务。

PROPAGATION_SUPPORTS ,supports ,支持

          支持当前事务,A如果有事务,B将使用该事务。

           如果A没有事务,B将以非事务执行。

PROPAGATION_MANDATORY,mandatory ,强制

          支持当前事务,A如果有事务,B将使用该事务。

          如果A没有事务,B将抛异常。

PROPAGATION_REQUIRES_NEW , requires_new ,必须新的

         如果A有事务,将A的事务挂起,B创建一个新的事务

         如果A没有事务,B创建一个新的事务

PROPAGATION_NOT_SUPPORTED ,not_supported ,不支持

       如果A有事务,将A的事务挂起,B将以非事务执行

       如果A没有事务,B将以非事务执行

PROPAGATION_NEVER ,never,从不

      如果A有事务,B将抛异常

      如果A没有事务,B将以非事务执行

PROPAGATION_NESTED ,nested ,嵌套

  A和B底层采用保存点机制,形成嵌套事务。


掌握:PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED

 

案例;转账案例(晚些再贴上来)


  学习到这里,Spring的知识点你已经基本掌握了,具体Spring和一些其他框架的整合,我会专门写一篇博客。这个系列的三篇Spring博客都很基础,而且是基于3.2的。然而Spring Boot,Spring家族中一个新的令人兴奋的项目。Spring致力于简化JAVA开发,而Spring Boot致力于让Spring本身更加简单!后期我应该会写关于SpringBoot的博客,有兴趣的朋友我们,我们可以共同学习,共同探讨。

  现在,你仅仅是一个Spring的user距离真正的developer还有很长的距离。Spring的源码是你必须去深究的。就像《Spring实战》的最后作者说道,你的Spring之路才刚刚开始。

0 0