springJdbcAndTransaction

 

一、     spring的JDBC

spring的DAO模块提供了对JDBC的支持。JdbcTemplage是springJDBC支持中主要的API,提供了访问数据库的一般功能。

实现步骤:

1.    搭建数据库

2.    引入需要的jar包

3.    编写代码业务

4.    例子

1)  在类中直接使用spring自带的连接池

创建执行连接数据库的类

public interfaceAccountDao {

   public voidgetDataSource();

}
@Controller

public classAccountDaoImpl implements AccountDao{

   public voidgetDataSource(){

      DriverManagerDataSource dataSource=newDriverManagerDataSource();

      dataSource.setDriverClassName("com.mysql.jdbc.Driver");

      dataSource.setUrl("jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&characterEncoding=utf8");

      dataSource.setUsername("root");

      dataSource.setPassword("1234");

      JdbcTemplate jdbcTemplate=newJdbcTemplate(dataSource);

      String sql="insertinto account values (null,?,?)";

      jdbcTemplate.update(sql,"aa",10000);

   } 

}

 

配置xml  

 <!-- 开启注解扫描 -->

   <context:component-scanbase-package="com.spring.tx"></context:component-scan>

测试

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations="classpath:applicationContext3.xml")

public classTestJdbcTemplate {

   @Autowired

   private AccountDao accoutDaoImpl;

   @Test

   public voidtestJTemplate(){

      accoutDaoImpl.getDataSource();

   }

}

2)  将数据连接池交给spring管理,即采用xml配置连接池

分析xml配置,首先,在使用jdbc连接数据库的类中,使用了dataSource,首先将连接池交给spring的xml,其次,JdbcTemplate使用了dataSource,而且在JdbcTemplate类中,dataSource是这个类的一个属性,所以,可以把dataSource注入这个类。

创建执行数据库连接的类

@Controller

public classAccountDaoImpl implements AccountDao{

   @Autowired

   private JdbcTemplate jdbcTemplate;

   public void getDataSourceXml(){

      String sql="insertinto account values (null,?,?)";

      jdbcTemplate.update(sql,"xmljdbc",10000);

   }

}

配置xml

   <!-- 开启注解扫描 -->

   <context:component-scanbase-package="com.spring.tx"></context:component-scan>

   <!-- 配置datasource的bean组件 -->

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

       <propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

       <propertyname="url"value="jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&amp;characterEncoding=utf8"/>

       <propertyname="username"value="root"/>

       <propertyname="password"value="1234"/>

    </bean>

   

    <!-- 将dataSource注入JdbcTemplate-->

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">

       <propertyname="dataSource"ref="dataSource"/>

    </bean>

测试略

3)  关于将dbcp和c3p0的连接池交给spring管理的xml配置

在导入相关jar包的前提下

Dbcp

    <!-- 配置dbcp -->

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

       <propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

       <propertyname="url"value="jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&amp;characterEncoding=utf8"/>

       <propertyname="username"value="root"/>

       <propertyname="password"value="1234"/>

    </bean>

C3p0

    <!-- 配置c3p0 -->

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

       <propertyname="driverClass"value="com.mysql.jdbc.Driver"/>

       <propertyname="jdbcUrl"value="jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&amp;characterEncoding=utf8"/>

       <propertyname="user"value="root"/>

       <propertyname="password"value="1234"/>

    </bean>

4)  关于使用JdbcTemplate执行增删改查操作

A.  增删改

   public voidgetDataSourceXml(){

      String sql="insertinto account values (null,?,?)";

      jdbcTemplate.update(sql,"xmljdbc",10000);

   }

   public void update(){

      String sql="updateaccount set name=? where id=?";

      jdbcTemplate.update(sql,"haha",905);

   }

   public void delete(){

      String sql="deletefrom account where id=?";

      jdbcTemplate.update(sql, 906);

   }

测试略

B.  查

在查询的实现中,需要配置对象关系映射类,这种操作思路是一般持久层框架会涉及到的。

   public Account selectOne(){

      String sql="select* from account where id=?";

      return jdbcTemplate.queryForObject(sql, newBeanMapper(), 905);

   }

   public List<Account>select(){

      String sql="select* from account";

      List<Account> alist=jdbcTemplate.query(sql,newBeanMapper());

      return alist;

   }

创建对象关系映射类

//创建字段映射类,对象关系映射,一些持久层框架也涉及到对象的关系映射

public classBeanMapper implements RowMapper<Account>{

   public AccountmapRow(ResultSetrs, intarg1) throwsSQLException {

      Account ac=newAccount();

      ac.setId(rs.getInt("id"));

      ac.setName(rs.getString("name"));

      ac.setMoney(rs.getDouble("money"));

      return ac;

   } 

}

二、   spring的事务实现

关于事务的介绍,请见。http://blog.csdn.net/xingzhishen/article/details/76559566

(一)   相关的类和接口

1.  PlatformTransactionManager

平台事务管理器,管理事物的类。通过不同的实现类,在不同的持久层框架,实现事务。

常用的实现类是:DataSourceTransactionManager

PlatformTransactionManager的方法

 void

commit(TransactionStatus status)
          Commit the given transaction, with regard to its status.

 TransactionStatus

getTransaction(TransactionDefinition definition)
          Return a currently active transaction or create a new one, according to the specified propagation behavior.

 void

rollback(TransactionStatus status)

 

2.  TransactionDefinition

事务定义接口,专门用于设定事务的属性。(如事务的隔离等级,传播行为,超时,只读等)

属性列表

static int

ISOLATION_DEFAULT
          Use the default isolation level of the underlying datastore.

static int

ISOLATION_READ_COMMITTED
          Indicates that dirty reads are prevented; non-repeatable reads and phantom reads can occur.

static int

ISOLATION_READ_UNCOMMITTED
          Indicates that dirty reads, non-repeatable reads and phantom reads can occur.

static int

ISOLATION_REPEATABLE_READ
          Indicates that dirty reads and non-repeatable reads are prevented; phantom reads can occur.

static int

ISOLATION_SERIALIZABLE
          Indicates that dirty reads, non-repeatable reads and phantom reads are prevented.

static int

PROPAGATION_MANDATORY
          Support a current transaction; throw an exception if no current transaction exists.

static int

PROPAGATION_NESTED
          Execute within a nested transaction if a current transaction exists, behave likePROPAGATION_REQUIRED else.

static int

PROPAGATION_NEVER
          Do not support a current transaction; throw an exception if a current transaction exists.

static int

PROPAGATION_NOT_SUPPORTED
          Do not support a current transaction; rather always execute non-transactionally.

static int

PROPAGATION_REQUIRED
          Support a current transaction; create a new one if none exists.

static int

PROPAGATION_REQUIRES_NEW
          Create a new transaction, suspending the current transaction if one exists.

static int

PROPAGATION_SUPPORTS
          Support a current transaction; execute non-transactionally if none exists.

static int

TIMEOUT_DEFAULT
          Use the default timeout of the underlying transaction system, or none if timeouts are not supported.

上面的属性,分别涉及到隔离等级,传播行为和超时。

事务的隔离等级:

PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。 
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。 
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。 
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED--嵌套事务,当A执行之后,就会在这个位置设置一个保存点。如果B没有问题,执行通过。如果B出现异常,运行客户根据需求回滚(选择回滚到保存点或者是最初始状态)。

3.  TransactionStatus

事务状态接口,这个接口中的setRollbackOnly()方法,可以实现事务的阻塞提交,对事务进行回滚。

(二)   实现事务的两种方式

业务需求,a账户向b账户转账。

业务分析,保证a出钱和b得钱的事务实现。

1.  编写基本业务

A.  创建web工程,导入jar包

B.  创建处理事务的类和三层结构包

C.  配置xml

D.  在dao层注入jdbc模板

E.  编写业务代码

F.  测试

G.  例子

创建三层的业务流程

Dao层

public interfaceAccountDao {

   public voidoutMoney(String name,doublemoney);

   public voidinMoney(String name,doublemoney);

}
@Repository

public classAccountDaoImpl extends JdbcDaoSupportimplementsAccountDao{ 

   public voidoutMoney(String name, double money) {

      String sql="updateaccount set money=money-? where name=?";

      this.getJdbcTemplate().update(sql,money,name);

   }

   public voidinMoney(String name, double money) {

      String sql="updateaccount set money=money+? where name=?";

      this.getJdbcTemplate().update(sql,money,name);

   }

}

Service层

public interfaceAccountService {

   public voidtransfer(String name1,Stringname2,doublemoney);

}
@Service

public classAccountServiceImpl implements AccountService{

   @Autowired

   private AccountDao accountDaoImpl;

   @Override

   public voidtransfer(String name1, Stringname2, doublemoney) {

      accountDaoImpl.outMoney(name1,money);

      accountDaoImpl.inMoney(name2,money);

   }

}

Web层或者测试层

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations="classpath:applicationContext4.xml")

public classTestTransaction {

   @Autowired

   private AccountService accountServiceImpl;

   @Test

   public voidtestTransaction(){

      accountServiceImpl.transfer("aa","bb",1000);

   }

}

配置xml

   <!-- 开启注解扫描 -->

   <context:component-scanbase-package="com.spring.tx2"></context:component-scan>

    <!-- 配置c3p0 -->

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

       <propertyname="driverClass"value="com.mysql.jdbc.Driver"/>

       <propertyname="jdbcUrl"value="jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&amp;characterEncoding=utf8"/>

       <propertyname="user"value="root"/>

       <propertyname="password"value="1234"/>

    </bean>

    <!-- 将dataSource注入JdbcTemplate-->

    <!-- <beanid="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate" >

       <propertyname="dataSource" ref="dataSource" />

    </bean> -->

    <bean id="accountDaoImpl" class="com.spring.tx2.AccountDaoImpl">

       <propertyname="dataSource"ref="dataSource"/>

</bean>

H.  关于简化dao层,spring提供了很多用于简化dao层开发的类。在jdbc连接数据库上,dao层类可以继承JdbcDaoSupport类。由于这个类拥有下面的属性和方法:

   privateJdbcTemplate jdbcTemplate;

   public final voidsetDataSource(DataSourcedataSource) {

      if (this.jdbcTemplate ==null || dataSource != this.jdbcTemplate.getDataSource()){

         this.jdbcTemplate =createJdbcTemplate(dataSource);

         initTemplateConfig();

      }

   }

Jdbcdao支持类中,带有jdbc模板,而且已经set dataSource,所以在xml或者注解中不用再赋予dao层类jdbc模板对象,只需赋予其dataSource属性就可以从父类生成jdbc模板。

2.  编程式事务管理

通过编写java代码的方式,实现事务。Spring提供了管理事务的模板TransactionTemplate,简化了编程式事务的代码,但是一般不常用这种方式。

步骤:

A.  配置事务管理器,实现PlatformTransactionManager。

B.  配置事务管理模板。

C.  将事务管理模板注入事务管理类

D.  在事务业务层使用事务管理模板实现事务

E.  例子

配置事务管理器

   <!-- 开启注解扫描 -->

   <context:component-scanbase-package="com.spring.tx2"></context:component-scan>

    <!-- 配置c3p0 -->

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

       <propertyname="driverClass"value="com.mysql.jdbc.Driver"/>

       <propertyname="jdbcUrl"value="jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&amp;characterEncoding=utf8"/>

       <propertyname="user"value="root"/>

       <propertyname="password"value="1234"/>

    </bean>

    <!-- 将dataSource注入JdbcTemplate-->

    <!-- <bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate" >

       <propertyname="dataSource" ref="dataSource" />

    </bean> -->

    <bean id="accountDaoImpl" class="com.spring.tx2.AccountDaoImpl">

       <propertyname="dataSource"ref="dataSource"/>

    </bean>

    <!-- 配置事务管理器

       事务的执行,需要保证连接的唯一,所以要把dataSource注入事务管理类

     -->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <propertyname="dataSource"ref="dataSource"/>

    </bean>

    <!-- 配置事务管理模板 -->

    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">

       <propertyname="transactionManager"ref="transactionManager"/>

    </bean>

    <!-- 将事务模板注入需要实现事务的业务类 -->

    <bean id="accountServiceImpl" class="com.spring.tx2.AccountServiceImpl">

       <propertyname="transactionTemplate"ref="transactionTemplate"/>

</bean>

在业务层使用事务模板实现事务

public classAccountServiceImpl implements AccountService{

   private TransactionTemplatetransactionTemplate;

   public voidsetTransactionTemplate(TransactionTemplate transactionTemplate) {

      this.transactionTemplate =transactionTemplate;

   }

   @Autowired

   private AccountDao accountDaoImpl;

   @Override

   public void transfer(final Stringname1,final Stringname2,finaldouble money) {

      transactionTemplate.execute(newTransactionCallbackWithoutResult() {

         protected voiddoInTransactionWithoutResult(TransactionStatus arg0) {

            accountDaoImpl.outMoney(name1,money);

            accountDaoImpl.inMoney(name2,money);

         }

      });  

   }

}

3.  声明式事务管理

声明式事务管理底层采用了AOP技术实现。

1)  基于AspectJ的xml的方式

核心步骤:

A.  配置事务管理器

B.  配置事务增强,即事务通知,就是要使用事务管理器来作用于事务单元

C.  配置配置AOP的切面,即形成事务增强与切入点的实现,通过切面将事务增强到事务单元

D.  测试

E.  例子

配置事务管理器,事务增强,以及切面,所有的业务都在xml中实现

   <!-- 开启注解扫描 -->

   <context:component-scanbase-package="com.spring.tx2"></context:component-scan>

    <!-- 配置c3p0 -->

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

       <propertyname="driverClass"value="com.mysql.jdbc.Driver"/>

       <propertyname="jdbcUrl"value="jdbc:mysql://localhost:3306/jdbc_transaction?useUnicode=true&amp;characterEncoding=utf8"/>

       <propertyname="user"value="root"/>

       <propertyname="password"value="1234"/>

    </bean>

    <!-- 将dataSource注入JdbcTemplate-->

    <!-- <bean id="jdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate" >

       <propertyname="dataSource" ref="dataSource" />

    </bean> -->

    <bean id="accountDaoImpl" class="com.spring.txxml.AccountDaoImpl">

       <propertyname="dataSource"ref="dataSource"/>

    </bean>

    <!-- 配置事务管理器

       使用PlatformTransactionManager的实现类DataSourceTransactionManager

       事务的执行,需要保证连接的唯一,所以要把dataSource注入事务管理类

     -->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <propertyname="dataSource"ref="dataSource"/>

    </bean>

    <!-- 配置事务增强的方法及其属性 -->

    <tx:adviceid="txAdvice"transaction-manager="transactionManager">

       <!-- 配置添加事务的方法

          同时,可以为事务的业务设置不同的属性

       -->

       <tx:attributes>

          <tx:methodname="transfer"/>

       </tx:attributes>

    </tx:advice>

    <!-- 配置切面 -->

    <aop:config>

       <aop:advisoradvice-ref="txAdvice"pointcut="execution(**..*.AccountServiceImpl.transfer(..))"/>

    </aop:config>

    <bean id="accountServiceImpl" class="com.spring.txxml.AccountServiceImpl"/>

F.  设置事务的相关属性

isolation:设置隔离等级      propagation:设置传播行为       time-out:设置超时时限       read-only:设置只读

实例略,请按需配置。形式如:

<tx:method name="transfer"isolation="DEFAULT"propagation="REQUIRED"read-only="false"timeout="-1"/>

2)  基于AspectJ的注解方式

核心步骤:

A.  配置事务管理器

B.  开启事务管理的注解功能

C.  在事务实现类上标注@Transactional

D.  测试

E.  例子

配置事务管理器和开启事务注解

    <!-- 配置事务管理器

       使用PlatformTransactionManager的实现类DataSourceTransactionManager

       事务的执行,需要保证连接的唯一,所以要把dataSource注入事务管理类

     -->

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

       <propertyname="dataSource"ref="dataSource"/>

    </bean>

   <!-- 开启事务的注解功能 -->

   <tx:annotation-driventransaction-manager="transactionManager"/>

标注事务类或事务方法

//标注类的注解,为所有的方法添加事务处理,也可以单独用在某个方法上。

@Transactional

public classAccountServiceImpl implements AccountService{

   @Autowired

   private AccountDao accountDaoImpl;

   @Override

   public voidtransfer(String name1,Stringname2,doublemoney) {

            accountDaoImpl.outMoney(name1,money);

            accountDaoImpl.inMoney(name2,money);

   }

}

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值