Spring整合JDBC及事务处理

时间:2022-01-22 21:35:27

 1.Spring整合JDBC

  DAO是数据访问对象(data access object)的简写。接口是实现松耦合的关键,Spring也鼓励使用接口,但不是强制的。

  捕获异常时希望能尝试从异常状态中恢复,JDBC的SQLException是编译时异常,捕获了之后大部分情况下我们也是无能为力,无法恢复。

  Spring的异常体系提供的异常是运行时异常,不要求强制捕获并处理。使用Spring模板时我们甚至可以不用去关心这些异常,手动地捕获也是可以的。

       Spring整合JDBC及事务处理

Spring中支持的模板类型如下:

Spring整合JDBC及事务处理

  

  Spring为JDBC提供了3个模板类:

  Spring整合JDBC及事务处理

  从Spring 3.1开始,JdbcTemplate和NamedParameterJdbcTemplate提供了SimpleJdbcTemplate的功能。SimpleJdbcTemplate被标注为过时,使用JdbcTemplate和NamedParameterJdbcTemplate即可。

  Spring 3.1之前的可以使用的是SimpleJdbcTemplate,支持泛型和可变长度参数。JdbcTemplate将会去捕获并抛出可能出现的Spring数据库操作异常,代码中不需要关心。

  //这里用的不是占位符,要注意

  String sql2 = "select id,tname,tpwd from tadd where tname = :tname";

  RowMapper<UserBean> rw = new RowMapper<UserBean>(){

  @Override

    public UserBean mapRow(ResultSet paramResultSet, int paramInt)

     throws SQLException {

      UserBean ub = new UserBean();

  ub.setId(paramResultSet.getObject("id") + "");

      ub.setName(paramResultSet.getObject("tname") + "");

      ub.setPassword(paramResultSet.getObject("tpwd") + "");

      return ub;

    }

  };

  Map<String, String> map = new HashMap<String, String>();

  map.put("tname", "p");

    UserBean ub = jdbctemplate.queryForObject(sql2, map, rw);    //UserBean ub = jdbctemplate.queryForObject(sql2, map, new BeanPropertyRowMapper(UserBean.class));

    System.out.println(ub.getName() + "," + ub.getPassword());

   queryForObject只返回一条记录,如果是多条记录应该用query方法。queryForString(String sql,String.class)将返回字符串型的结果。如果没有对应的javabean,可以用queryForMap和queryForList方法。queryForMap返回一条记录,queryForList返回多条记录。

  

如果希望能够取得插入记录的主键值,可以调用回调函数,也可以在回调函数中对connection做更多的处理。

static Integer id=0;

public static int getId(final Person person) {
JdbcTemplate jdbcTemplate=new JdbcTemplate(JDBCUtils.getDataSource()); jdbcTemplate.execute(new ConnectionCallback(){
//传递的参数为Connection conn,自己可以在conn内写希望完成的功能
public Object doInConnection(Connection conn) throws SQLException,DataAccessException{
String sql="insert into person(name) values (?)";
PreparedStatement ps=conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);//返回所插入数据的主键
for(int i=0;i<10;i++){
ps.setString(1, person.getName());
ps.addBatch(); //批处理,将SQL语句进行打包
}
//ps.executeUpdate();
ps.executeBatch(); //没有这一行是不会插入数据的
ResultSet rs=ps.getGeneratedKeys();
while(rs.next())
id=rs.getInt(1);
return id;
}
});
return id;
}

  Hibernate,ibatis等持久层框架可以提供比JDBC更为强大的特性,如下所列:

Spring整合JDBC及事务处理

        Spring整合JDBC及事务处理

 2.事务的定义及处理

  Spring整合JDBC及事务处理

  Spring整合JDBC及事务处理

  Spring整合JDBC及事务处理

  Spring整合JDBC及事务处理

上图是Spring所支持的事务传播行为所支持的规则。

  事务的隔离级别如下图所示:

       Spring整合JDBC及事务处理

不是所有的数据库都完整的支持上面所列的隔离级别,数据库不支持时即使进行了设置也不会起作用。

  Spring整合JDBC及事务处理

  Spring整合JDBC及事务处理

  Spring整合JDBC及事务处理

tx:method  name =”*”将匹配除了save*之外的其他方法。

  使用Druid数据库连接池。

先在配置文件引入tx命名空间,再引入TranstactionManager的bean,还需要打开如下开关:

  <tx:annotation-driven transaction-manager = "txManager">

Spring整合JDBC及事务处理

在数据库操作bean上加上@Transactional注解开启事务,方法中的多条语句将在一个事务中完成,否则每条语句在一个事务中完成。

@Transactional

public class PersonServiceBean implements PersonService

运行期例外(unckecked exception),事务的操作将被回滚。预知的例外(checked  exception),事务的操作将不会回滚。

可以在方法上加上@Transactional注解来改变上述的默认行为

@Transactional(rollbackFor = Exception.class)

public void delete(Integer id) throws Exception{

}

希望运行期例外不进行事务回滚,加上的是

@Transactional(noRollbackFor = RuntimeException.class)

public void delete(Integer id) {

    int i = 3/0;

}

如果一些操作不需要开启事务,例如查询操作,可以向下面这样操作:

@Transactional(propagation = Propagation.NOT_SUPPORTED)

public Person getPerson(Integer id)

bean上开启了事务功能,上面所有的方法默认都是要进行事务操作的,默认的不需要加任何注解,等同于下面的形式:

 @Transactional(propagation = Propagation.REQUIRED)

public Person savePerson(Person person)

从属性文件中读取数据库连接池参数信息。