码迷,mamicode.com
首页 > 数据库 > 详细

spring的使用-jdbc、事务

时间:2018-11-17 16:02:32      阅读:192      评论:0      收藏:0      [点我收藏+]

标签:comm   not   iso   父类   哪些   oid   相关信息   tco   bool   

spring对数据库的操作:jdbcTemplate操作及事务管理

1.jdbcTemplate操作数据库:

      1. 导入jar包(3个)

            spring-jdbc-4.2.4.RELEASE.jar

            spring-tx-4.2.4.RELEASE.jar

            以及jdbc驱动jar包

      2. 创建连接池

            DriverManagerDataSource dataSource = new DriverManagerDataSource();          //为spring内置连接池

      3. 设置连接池参数

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

            dataSource.setUrl("jdbc:mysql:///springtest");

            dataSource.setUsername("root");

            dataSource.setPassword("abc");

      4. 创建JdbcTemplate对象设置参数

            JdbcTemplate jdbcTemplate=new JdbcTemplate();

            jdbcTemplate.setDataSource(dataSource);

      6. 执行sql语句

            jdbcTemplate.execute("update t_user set name=‘张三‘ where id=1");//execute方法可以执行任意sql

           

      总结:jdbcTemplate类似于jdbcUtils中的queryrunner对象,需要传入一个连接池,可以执行sql语句

 

2.使用spring容器简化上述操作

      将连接池对象DriverManagerDataSource,和temple对象jdbcTemplate都交给spring管理

            1. applicationContext.xml配置:

                  spring内置的连接池DriverManagerDataSource,如下:      //如果要使用c3p0连接池:先导入两个c3p0的两个jar包,在下面的class中传入ComboPooledDataSource全类名,并采用set方法设置响应属性即可

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

                          <property name="driverClassName" value="com.mysql.jdbc.Driver" /> //采用set方法注入属性,DriverManagerDataSource有对应的set方法

                          <property name="url" value="jdbc:mysql:///springtest" />

                          <property name="username" value="root" />

                          <property name="password" value="abc"></property>

                  </bean>

 

                  配置jdbcTemplate

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

                        <property name="dataSource" ref="driverManagerDateSource"></property>      //set方法注入属性

                  </bean>

           

            2. 简化后操作:

                  @RunWith(SpringJUnit4ClassRunner.class)

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

                  public class JdbcTemplateTest2 {

                       @Autowired

                       private JdbcTemplate jdbcTemplate;    //从spring容器中获取对象

 

                       @Test

                       public void test1() {

                       jdbcTemplate.execute("update t_user set sex=‘女‘");   //执行sql语句

                       }

                  }

                      

3.通过JdbcDaoSurport 获取jdbctemplate进一步简化操作           //只需要向jdbcDaoSurport中注入连接池即可

      JdbcDaoSurport类中声明了jdbctemplate和setJdbcTemplate(),和连接池setDataSource()方法。

     

      public class AccountDAOImpl extends JdbcDaoSupport implements IAccountDAO {       //让dao继承JdbcDaoSuppory,需要注入连接池

 

            @Override

            public void accountOut(String outname, double money) {

                  this.getJdbcTemplate().update("update account set money=money-? where name=?", money, outname);       //注入连接池后,直接调用getJdbcTemplate();的方法获取JdbcTemplate对象

            }

      }

     

      如果使用注解方式,注入dataSource的方式:

            @Component

            public class AccountDAOImpl extends JdbcDaoSupport implements IAccountDAO {

                 

                  @Autowired

                  public void setDs(DataSource ds){ //注入时,会在spring容器中查找DataSource的实现类对象,并当作参数传入

                       super.setDataSource(ds);   //调用父类的方法实现连接池注入,注入连接池后,父类会自动创建jdbcTemplate对象

                  }

                  ...

            }

           

4.Jdbctemplate应用--crud操作         

      增删改:update("");           //传入sql语句,与queryrunner一样

            jdbcTemplate.update("update t_user set name=? where id=?", "tom", 1);  //sql语句还可以是insert into 或delete from ...

      查:queryForObject("",class);

 

 

5.引入外部属性文件properties

      1. 创建properties属性文件如:db.properties

     

      2. 在applicationContext.xml中引入properties文件:

            <context:property-placeholder location="classpath:db.properties" />

           

      3. 在配置文件或注解中均可使用${name}方式来获取属性:

            <!-- 创建c3p0连接滨 -->

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

                  <property name="driverClass" value="${jdbc.driverClass}" />       //获取properties外部文件中的属性并注入

                  <property name="jdbcUrl" value="${jdbc.url}" />

                  <property name="user" value="${jdbc.username}" />      //jdbc.username如果改为usesrname会出错??

                  <property name="password" value="${jdbc.password}" />

            </bean>

     

     

6.事务管理机制(三个接口):

      1. PlatformTransactionManager    --->平台事务管理器,在不同的持久化层,事务代码不一样

            常用的实现类:

                  DataSourceTransactionManager   主要针对于JdbcTemplate开发  MyBatis开发

                  HibernateTransactionManasger    主要针对于Hibernate开发

                  JpaTransactionManager                主要针对于JPA开发

           

            接口中的三个方法:

                  getTransaction();    //开启事务

                  commit();         //提交事务

                  rollback();        //回滚事务

 

      2. TransactionDefinition     --->定义事务的一些相关信息 例如 隔离 传播 超时 只读

            隔离:

                  ISOLATION_DEFUALT              它使用后端数据库的默认隔离级别(spring中选项)

                  ISOLATION_READ_UNCOMMITTED     不能解决问题,会发生脏读 不可重复读 虚读

                  ISOLATION_READ_COMMITTED    可以解决脏读 会产生不可重复读与虚读。

                  ISOLATION_REPEATABLE_READ     可以解决脏读,不可重复读 解决不了虚读

                  ISOLATION_SERIALIZABLE             串行化,可以解决所有问题

 

            传播:  //解决的是两个被事务管理的方法互相调用问题(A调用B)。它与数据库没关系,是程序内部维护的问题

                  PROPAGATION_REQUIRED       默认值 两个操作处于同一个事务,如果之前没有事务,新建一个事务。 两个事务要么同时成功,要么同时失败

                  PROPAGATION_REQUIRES_NEW     B会新建一个事务,两个操作处于不同的事务,A和B互不影响

                  PROPAGATION_NESTED                它是一种嵌套事务,它是使用SavePoint来实现的。A可以影响B,但是B不能影响A。事务回滚时可以回滚到指定的savepoint, 注意:它只对DataSourceTransactionManager有作用

                                                    

                  PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务

                  PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常

                  PROPAGATION_NOT_SUPPORTED 以非事务运行,如果有事务存在,挂起当前事务

                  PROPAGATION_NEVER 以非事务运行,如果有事务存在,抛出异常

 

            超时:int TIMEOUT_DEFAULT = -1;     默认值是-1 它使用的是数据库默认的超时时间

            只读:boolean isReadOnly();         它的值有两个true/false,如果选择true一般是在select操作时

           

      3. TransactionStatus     --->定义了事务状态信息,在事务运行过程中,得到某个时间点的状态

           

     

7.spring事务管理-事务管理两种方式

      1.   编码方案 不建议使用,它具有侵入性。在原有的业务代码基础上去添加事务管理代码

     

            @Autowired

            private PlatformTransactionManager transactionManager;      //注入方式获取事务管理器对象

     

            @Override

            public void account(String outname, String inname, double money)  {

                  DefaultTransactionDefinition def = new DefaultTransactionDefinition(); //创建TransactionDefinition实现类对象

                def.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);      //设置事务相关信息参数

            def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);     

                  def.setReadOnly(false);

                  def.setTimeout(TransactionDefinition.TIMEOUT_DEFAULT);

                 

                  TransactionStatus status = transactionManager.getTransaction(def); //开启事务,需要传入事务定义TransactionDefinition对象

                                                                                                                     //此处得到的是一个事务状态的对象

                  try {

                       // 逻辑代码

                       // 从outname转出money

                       accountDao.accountOut(outname, money);

                       int a = 10 / 0; // 一定会抛出异常

                       // 向inname转入money

                       accountDao.accountIn(inname, money);

                      

                  } catch (Exception e) {

                       //事务回滚

                       transactionManager.rollback(status);   //传入事务状态对象记录状态信息

                  } finally {

                       //提交事务

                       transactionManager.commit(status);

                  }

            }

     

            总结:三个接口的对象相互配合完成事务控制,PlatformTransactionManager对象负责开启、关闭、回滚事务,

                  TransactionDefinition,负责封装事务相关信息,      TransactionStatus负责记录事务状态信息

     

      2.   声明式事务控制,基于AOP对目标进行代理,添加around环绕通知。      //优点:不具有侵入性,不需要修改原来的业务代码

            a.xml 配置文件实现

                  第一步:在applicationContext.xml文件中添加aop与tx的名称空间

                  第二步:配置事务管理器

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

                             <property name="dataSource" ref="c3p0DataSource"/>        //需要注入连接池

                       </bean>

 

                  第三步:配置通知   //Spring为我们提供了一个TransactionInterceptor来完成增强, 对于这个增强,可以使用spring为我们提供的一个标签<tx:advice>来完成操作

                       <tx:advice id="txAdvice" transaction-manager="transactionManager">

                             <tx:attributes>

                                   <tx:method name="account" />

                             </tx:attributes>

                       </tx:advice>

                      

                       <tx:method>中的属性 //相当于定义事务相关信息

                       name:必须的,对哪些方法进行事务控制

                       isolation 可选 设置事务隔离级别 默认是DEFAULT

                       propagation:可选 设置事务传播 默认值 REQUIRED

                       timeout 可选 超时时间 默认值-1

                       read-only 可选 默认值是false 如果不是只读,它可以对insert update delete操作,如果是只读不可以。

                       rollback-for 可选 可以设置一个异常,如果产生这个异常,触发事务回滚

                       no-rolback-for 可选 可以设置一个异常,如果产生这个异常,不会触发事务回滚

                 

                  第四步:配置切面 //使用的是传统的spring的advice,需要使用<aop:advisor>标签配置切面

                       <aop:config>

                             <aop:pointcut

                                   expression="execution(* cn.itheima.service.IAccountService.account(..))" id="txPointcut"/>

                             <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>

                       </aop:config>

 

                      

           

            b.注解实现

                  1. 配置事务管理器       //需要提前配置连接池

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

                             <property name="dataSource" ref="c3p0DataSource"/>        //必须注入dataSource

                       </bean>

                  2. 开启注解事务

                       <tx:annotation-driven transaction-manager="transactionManager"/>            //必须传入事务管理器

 

                  3. 方法或类上使用注解:

                  @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)      //可以在括号中加入事务信息,也可省略

                       @Override

                       public void account(String outname, String inname, double money) {

                             // 从outname转出money

                             accountDao.accountOut(outname, money);

                             int a = 10 / 0; // 一定会抛出异常

                             // 向inname转入money 

                             accountDao.accountIn(inname, money);

                       }

 

     

this的用法:为当前类的对象的引用,当子类对象调用父类成员时,父类中的this相当于下面的f:

      Z继承F

      F f=new Z();     这里的f就类似于this

      此时this为子类对象的父类引用(多态),当调用getClass()方法时,获取的时子类的字节码对象

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

      

spring的使用-jdbc、事务

标签:comm   not   iso   父类   哪些   oid   相关信息   tco   bool   

原文地址:https://www.cnblogs.com/liuxuelin/p/9973750.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!