spring JDBC-事务管理

一、Spring 中的JDBC
Spring中封装了JDBC的ORM框架,可以用它来操作数据,不需要再使用外部的OEM框架(MyBatis),一些小的项目用它。

步骤:
1.导入JDBC相关的Jar包,应用dbcp连接池
aopalliance-1.0.0.jar
aspectjweaver-1.6.8.jar
commons-dbcp-1.4.jar // 数据库连接池
commons-logging-1.1.1.jar
commons-pool-1.5.3.jar
mysql-connector-java-5.1.38-bin.jar
spring-aop-4.3.10.RELEASE.jar
spring-aspects-4.3.10.RELEASE.jar
spring-beans-4.3.10.RELEASE.jar
spring-context-4.3.10.RELEASE.jar
spring-context-support-4.3.10.RELEASE.jar
spring-core-4.3.10.RELEASE.jar
spring-expression-4.3.10.RELEASE.jar
spring-jdbc-4.3.10.RELEASE.jar //jdbc 操作的对象包
spring-tx-4.3.10.RELEASE.jar //数据库中的事务处理包

2.在配置文件中配置连接池数据源,及JdbcTemplate对象
<

!-- 加载连接数据的的属性文件 -->
   <bean id="propertyPlaceholderConfigurer"
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
       <property name="location" value="classpath:config/jdbc.properties"/>
   </bean>
   <!-- 配置数据源对象,此数据源用的是dbcp连接池 -->
   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
     <!-- 连接数据库的基本配置  ${driver}读取到属性文件的键对应的值-->
     <property name="driverClassName" value="${driver}"/>
     <property name="url" value="${url}"/>
     <property name="username" value="${username}"/>
     <property name="password" value="${password}"/>
     <!-- 配置连接池相关属性,初始大小,最大连接数,最大空闲,最小空闲,最大空闲时间 -->
     <property name="initialSize" value="${initialSize}"/>
     <property name="maxActive" value="${maxActive}"/>
     <property name="maxIdle" value="${maxIdle}"/>
     <property name="minIdle" value="${minIdle}"/>
     <property name="maxWait" value="${maxWait}"/>
   </bean>
   <!-- Spring框架封装好的JDBC对象,可以操作数据 -->
   <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
      <property name="dataSource" ref="dataSource"/>
   </bean>

3.在程序中获取到JdbcTemplate对象,此对象就可以操作数据。

@Service // 扫描到IOC容器中
public class GradeService {
	@Autowired // 自动从IOC容器中注入对象
	JdbcTemplate jdbcTemplate;

	// 查询所有
	public List<Grade> getGrades() {
		String sql = "select * from grade";
		// 数据行映射器,映射数据行的列与实体对象的属性对应
		RowMapper<Grade> rm = new BeanPropertyRowMapper<>(Grade.class);
		// 可以把查询的结果集中的数据行一行行封装成实体对象
		List<Grade> grades = jdbcTemplate.query(sql, rm);
		return grades;
	}

	// 根据ID查询单个对象
	public Grade getGradeById(int id) {
		RowMapper<Grade> rm = new BeanPropertyRowMapper<>(Grade.class);
		String sql = "select * from grade where gradeId=?";
		return jdbcTemplate.query(sql, new Object[] { id }, rm).get(0);
	}

	// 根据ID查询年级名称,返回单个值
	public String getGradeNameById(int id) {
		String sql = "select gradeName from grade where gradeId=?";
		return jdbcTemplate.queryForObject(sql, new Object[] { id }, String.class);
	}

	// 根据年级名称查询ID,返回单个值
	public int getGradeIdByName(String name) {
		String sql = "select gradeId from grade where gradeName=?";
		return jdbcTemplate.queryForObject(sql, new Object[] { name }, int.class);
	}
	//添加,增,删,改调用相同的方法,只是SQL指令不同
	public int add(Grade g) {
		String sql = "insert into grade values(null,?)";
		return jdbcTemplate.update(sql, g.getGradeName());
	}
}

二、事务管理
事务是数据库中的事务,在数据库中,每一个SQL指令都是独立的事务,数据库的事务类型自动提交型,
事务有4大特性:原子性,一致性,隔离性,持久性。
有时,我们一个业务逻辑需要多条SQL指令一起完成,比如下订单,先向订单表插入一条数,再根据生成的订单号,再向订单详细表插入数据,就需要多条SQL语句支撑。但是数据库认为每一条SQL指令是一个事务,假如一条SQL有问题不能执行,不会影响的SQL指令执行的。只有用事务才可以控制。事务的作用是把一批SQL指令作为一个整体,一起执行或不执行。
转账功能,修改的SQL语句就需要2条,向交易表插入至少1条SQL语句。
在开发中,我们用自定义事务来处理一次要执行多条SQL指令的业务。

事务管理的步骤:
1.在配置文件中配置事务管理机制:

<!-- 启用事务管理器 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置事务管理器 -->
<bean id="transactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

2.建议在业务层的方法前加入 @Transactional注解,此注解的作用是把方法里面的所有操作数据库的SQL指令整合为一个事务。

/**
	 * 事务管理,此方法里面所有的操作数据库的SQL指令整合为一个事务
	 * @Transactional这个注解可以在方法前,也可以在类前。
	 * 加在方法前,表示此方法应用事务机制,在类前,则这个类中所有的方法都应用事务机制
	 */
	@Transactional
	public void zhanzhang(String INbank,String OUTbank,double money) {
		try {
			bankDao.inMoney(INbank, money);
			bankDao.outMoney(OUTbank, money);
			System.out.println("转账成功!");
		} catch (Exception e) {
			System.out.println("转账失败,原因是:" + e.getMessage());
		}
	}

三、事务超时设置:
@Transactional(timeout=30) //默认是30秒

四、事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)
读取未提交数据( 会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED)
读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ)
可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE)
串行化
MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED

五、事务传播行为
@Transactional(propagation=Propagation.REQUIRED)
如果有事务, 那么加入事务, 没有的话新建一个(默认)
@Transactional(propagation=Propagation.NOT_SUPPORTED)
容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW)
不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY)
必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER)
必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS)
如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值