Spring JDBC 和 事务 的基本使用

Posted Drajun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring JDBC 和 事务 的基本使用相关的知识,希望对你有一定的参考价值。

Spring JDBC

一、    作用

方便我们操作数据库;

二、    基本使用

  1. 配置

首先配置数据源(加载数据库驱动类、数据库URL、用户名密码…..);

 

  1. 注册JDBC模板

即配置class=” org.springframework.jdbc.core.JdbcTemplate”的bean,我们需要使用该对象来对数据库进行操作;该bean需要配置dataSource属性,ref值为数据源bean;

 

  1. 通过继承JdbcDaoSupport类来使用jdbc模板

该类已经编写了JdbcTemplate字段,只要继承该类,并在配置中注入JdbcTemplate字段的JDBC模板bean引用,便可以在JdbcDaoSupport子类中使用jdbc模板了,使用方式为: this.getJdbcTemplate().增删改查方法...;

 

  1. 直接使用JdbcTemplate对象来操作数据库

即:JdbcTemplate 对象名 = Ioc容器对象名.getBean(“JDBC模板beanID”);

这样可以不继承JdbcDaoSupport类;

 

  1. 单行 增删改

this.getJdbcTemplate().update(sql语句, 参数1…,参数2,参数3,…..);

增删改都是使用.update方法,参数列表是可变的,可以有任意个;该方法有返回值,返回受影响的行数

 

  1. 批量 增删改

this.getJdbcTemplate().batchUpdate(sql语句, List<Objcet[]>参数);

其中List<Object[]>保存每行参数值(比如:list对象.add(new Object[]{id,”name”,”phone”}))

 

  1. 查询一列数据

一行:this.getJdbcTemplate().queryForObject(sql语句,数据类型.class,参数1,参数2,….);

多行:this.getJdbcTemplate().queryForList(sql语句,数据类型.class,参数1,参数2,….);

 

  1. 查询多列数据

this.getJdbcTemplate().queryForObject(sql, RowMapper对象, 参数1,参数2,….);

其中RowMapper对象是查询到的列与一个对象的映射;

创建RowMapper:

(1)   RowMapper<对象> 实例名 =new BeanPropertyRowMapper<>(对象.class);

(2)   写一个类,实现RowMapper<T>接口,T为要映射的对象,该接口中有方法mapRow(ResultSet参数,int参数),其中ResultSet参数表示当前行,使用参数名.get基本数据类型(数据库列名/列号)获取到指定列,而第二个参数是当前行号;

(3)   无论是查询一行还是多行,Rowmapper会自动遍历,所有都用以上方法即可;

 

  1. 具名参数JDBC模板(NamedParameterJdbcTempate)

该JDBC模板与JdbcTemplate作用一致,但可以在SQL语句中需要写入的参数名与JDBC模板的增删改查方法中的参数名相对应

(0)   同样,需要先配置bean,该类的构造器是有参数的,配置时需要通过构造器注入方式把dataSource注入给它;

(1)   原本JdbcTemplate对象中的增删改查SQL语句需要参数时,就使用?号当作一个占位符,然后在方法中按sql语句参数顺序来写入参数;

例:sql=”select * from table where id=? and name=? ”

         this.getJdbcTemplate().queryForObject(sql, RowMapper对象,id,name);

         这里id和name参数的顺序要和sql语句中参数顺序一致

(2)   在具名参数JDBC模板中,用 :参数名 来占位,增删改差方法有一个map,该map键为sql语句中的参数名,值为需要操作的值;

例:sql=”select * from table where id=:id and name=:name ”

map.put(“id”,id值);  map.put(“name”,name值);

具名参数JDBC模板对象.query(sql,map);

(3)   也可以使用.update(sql语句, SqlParameterSource对象)来操作;

其中:SqlParameterSource 对象名= new BeanPropertySqlParameterSource(对象实例);

这样可以将对象封装在一起,方便写入,需要注意的是,该方法sql语句占位符中名字需要和对象里的字段对应;

 

Spring 事务

〇、作用

  1. 事务具有ADID特性;
  2. 用来确保数据的完整性和一致性;
  3. 和数据库的事务是同一个意思;
  4. 其底层实现实质也是Java的动态代理

基于注解使用事务

  1. 使用事务时,需要引入spring-tx的jar包,配置文件里也要引入tx命名空间

 

1.在XML配置文件中配置事务管理器的bean,id随意,

class=” org.springframework.jdbc.datasource.DataSourceTransactionManager”

该bean还得配置dataSource属性;

 

2.启用事务注解

<tx:annotation-driven transaction-manager="transactionManager"/>

 

3.使用注解

在类的某一方法上写@Transactional,则该方法就使用了事务,里面的代码要么全部执行成功,要么就失败时回滚;

 

  1. 事务的传播行为

(0)   意义:指定一个事务方法被另一个事务方法调用时,应该如何传播;

(1)   例如:方法A是购买一张电影票;方法B里有个for循环调用方法A实现购买多张电影票;两个方法都实现了事务,当出现问题时(for到第二张时余额不足、电影票不足…),是应该全部失败回滚呢,还是余额不足那部分回滚?

(2)   默认地,出现问题时,是全部失败(即方法A(被调用方法)的事务挂起,在方法B(调用方法)的事务内运行);

(3)   也可以在被调用方法上的@Transactional内加上参数:

propagation=Propagation.REQUIRES_NEW

实现运行到被调用的方法A时,方法B就挂起(即余额不足那部分回回滚,余额与电影票充足的部分就购买成功);

(4)   需要注意,使用事务传播行为时,调用方法和被调用方法应在不同的类里;

 

  1. 事务的隔离级别
    1. 可在@Transactional内加上参数设置该事务方法的隔离级别 isolation=Isolation.级别

1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.

 另外四个与JDBC的隔离级别相对应

2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

 

  1. 指定回滚
    1. 事务默认回滚异常为运行时异常(即方法运行时异常时,事务就回滚)
    2. 可在@Transactional中加参数,指定哪些异常回滚,哪些异常不回滚
    3. noRollbackFor/ noRollbackForClassNama ,  rollbackFor/ rollbackForClassNama

前者不回滚,异常也会抛出,但修改了的数据不会回到执行前

后者指定哪些异常要回滚

 

  1. 指定超时时间

在@Transactional 内加入timeout参数(值为整数,单位秒),指定该事务方法执行的时间,当方法执行超时时,会抛出超时异常;

 

一、基于XML文件使用事务(AspectJ框架)

  1. bean的配置如常,事务管理器配置如上;

 

  1. 不需要写 启用事务注解 的标签了;

 

  1. 配置事务的属性(类似AspectJ AOP的切面)

<tx:advice id=”id随意”  transaction-manager=”事务管理器的ID”>

  <tx:attributes>

          <tx:method name=”仅方法名(可用*号模糊匹配)”  各属性(比如传递、指定回滚、只读、超时….) propagation=”REQUIRES_NEW” />

          ….

若仅使用默认属性配置,则<tx:method name=”*” />

 

  1. 配置事务切入点(同AspectJ AOP),将方法、事务管理器和事务属性关联

<aop:config>

  写切入点表达式<aop: expression……>

 关联<aop:advisor advice-ref=”事务属性id”  pointcut-ref=”切入点表达式id” />

 

二、基于XML文件使用事务(Spring 自带的Aop框架)

  1. bean的配置如常,事务管理器配置如上;
  2. 不需要写 启用事务注解 的标签了;
  3. 生成事务代理:

<bean id=”随意ID”

class=”org.springframework.transaction.interceptor.TransactionProxyFactoryBean”>

事务管理器<property name=”transactionManager” ref=”事务管理器beanID”>

目标对象<property name=” target” ref=”目标对象beanID” >

事务参数<property name=”transactionAttributes”>

                       <props>

                              <prop key=”目标对象里的方法(仅方法名,可用*模糊匹配)”>

                                      各个参数值用逗号隔开(参数值比如PROPAGATION_RREQUIRED…)

                              </prop>

                       ……

其它:一个props里可以有多个prop;

事务属性参数值请查阅API文档;

-异常类名 表示发生此异常时回滚,+异常类名 表示发生此异常时不回滚。

 

ps.请自行查阅开发过程中需要使用的jar包

以上是关于Spring JDBC 和 事务 的基本使用的主要内容,如果未能解决你的问题,请参考以下文章

JDBC与Spring事务及事务传播性原理解析-上篇

JDBC与Spring事务及事务传播性原理解析-上篇

SSH框架的基本整合

Spring JPA无法提交jdbc事务的解决办法

如何配置 Spring 使 JPA(Hibernate)和 JDBC(JdbcTemplate 或 MyBatis)共享同一个事务

JDBC与Spring事务及事务传播性原理解析-下篇