Spring03

Spring jdbc Template
Spring提供了一个JDBC模板,它类似于dbutils工具
在这里插入图片描述
如何使用spring.jdbc.template?
第一:要导入相关jar包
在这里插入图片描述
第二:在这个基础上我们还需要导入
在这里插入图片描述在这里插入图片描述
第三:还需要导入相关的数据库驱动jar包
案例:
1.导入相关jar包
在这里插入图片描述
2.创建库与表`

CREATE DATABASE springtest;
CREATE TABLE t_user(
	
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	age INT,
	sex VARCHAR(20)
)
INSERT INTO t_user VALUES(NULL,'tom',20,'男');
INSERT INTO t_user VALUES(NULL,'fox',30,'男');
INSERT INTO t_user VALUES(NULL,'tony',40,'男');

3.编码

@Test
	public void test1(){
		//1.创建数据库连接池
		DriverManagerDataSource dataSource=new DriverManagerDataSource();
		//2.设置dataSource相关的属性(driverclass url username password)
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl("jdbc:mysql:///springtest");
		dataSource.setUsername("root");
		dataSource.setPassword("root");
		//3.创建一个JdbcTemplate来完成操作
		JdbcTemplate jdbcTemplate=new JdbcTemplate();
		jdbcTemplate.setDataSource(dataSource);
		jdbcTemplate.execute("update t_user set name='张三' where id=1");//execute方法可以执行任意sql
	}

使用spring内置的链接池DriverManagerDataSource

 <bean id="driverManagerDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource;">
   <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
   <property name="url" value="jdbc:mysql:///springtest"/>
   <property name="username" value="root"/>
   <property name="password" value="root"/>
 </bean>
 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <property name="dataSource" ref="driverManagerDataSource"></property>
 </bean>
public class JdbcTemplateTest2 {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Test
	public void test1(){
		//3.创建一个JdbcTemplate来完成操作
		jdbcTemplate.execute("update t_user set name='李四' where id=2");//execute方法可以执行任意sql
	}
}

C3P0开源链接池配置
1.导入c3p0相关的jar包
在这里插入图片描述
2.创建一个ComboPoolDataSource对象,设置相关的属性

 <!-- 创建c3p0链接池 -->
 <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 <property name="dirverClass" value="com.mysql.jdbc.Driver"/>
 <property name="jdbcUrl" value="jdbc:mysql:///springtest"/>
 <property name="user" value="root"/>
 <property name="password" value="root"/>
 </bean>

引入外部属性文件
Spring支持经常修改属性,在properties文件中声明,在xml配置文件中引入外部的properties文件的信息

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///springtest
jdbc.username=root
jdbc.password=root

在applicationContext.xml文件中引入

 <!-- 引入外部的properties文件 -->
   <context:property-placeholder location="classpath:db.properties"/>    

在自己配置中需要从properties文件中引入的信息可以使用${}方式来获取

 <!-- 创建c3p0链接池 -->
 <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 <property name="dirverClass" value="${jdbc.driverClass}"/>
 <property name="jdbcUrl" value="${jdbc.url}"/>
 <property name="user" value="${jdbc.username}"/>
 <property name="password" value="${jdbc.password}"/>
 </bean>

JdbcTemplate CRUD
只需要使用JdbcTemplate的update方法就可以执行insert update delete操作

jdbcTemplate.update("update t_user set name=? where id=?", "tom", 1);
jdbcTemplate.update("insert into t_user values(null,?,?,?)", "赵六", 30, "男");
jdbcTemplate.update("delete from t_user where id=?", 4);

执行select操作

简单数据返回

// 测试返回简单数据类型
	@Test
	public void test4() {
		String name = jdbcTemplate.queryForObject("select name from t_user where id=?", String.class, 2);
		System.out.println(name);
	}
	// 测试返回简单数据类型
	@Test
	public void test5() {
		Integer count = jdbcTemplate.queryForObject("select count(*) from t_user", Integer.class);
		System.out.println(count);
	}

复杂数据返回
在这里插入图片描述
注意:如果返回一个domain对象,可以使用queryForObject方法,如果返回的是List<?>对象,可以使用query方法,但是都需要使用RowMapper来对ResultSet进行处理

@Test
	public void test6(){
	User user=jdbcTemplate.queryForObject("select * from t_user where id=?", new RowMapper<User>(){

			@Override
			public User mapRow(ResultSet arg0, int arg1) throws SQLException {
				//完成结果集封装成user对象操作
				User user=new User();
				user.setAge(arg0.getInt("age"));
				user.setId(arg0.getInt("id"));
				user.setName(arg0.getString("name"));
				user.setSex(arg0.getString("sex"));
				return user;
			}
			
		},1);
	System.out.println(user);
	}
	//测试返回一个复杂的数据类型-List<User>
	@Test
	public void test7(){
		List<User> user=jdbcTemplate.query("select * from t_user", new RowMapper<User>(){
			@Override
			public User mapRow(ResultSet arg0, int arg1) throws SQLException {
				//完成结果集封装成user对象操作
				User user=new User();
				user.setAge(arg0.getInt("age"));
				user.setId(arg0.getInt("id"));
				user.setName(arg0.getString("name"));
				user.setSex(arg0.getString("sex"));
				return user;
			}
			
		});
		System.out.println(user);
	}

RowMapper它有一个实现类叫BeanPropertyRowMapper
如果使用BeanPropertyRowmapper,实体类必须提供一个无参数的public构造方法,类中的bean属性名称与表中的列要对应
注意:这个类是在spring2.0后提供

//使用BeanPropertyRowMapper来完成结果集到Bean封装
	@Test
	public void test8(){
		User user=jdbcTemplate.queryForObject("select * from t_user where id=?",new BeanPropertyRowMapper<User>(User.class),1);
		
		System.out.println(user);
	} 

Spring事务管理
案例:转账操作
1.创建一个账户表

CREATE TABLE account(
	id INT PRIMARY KEY AUTO_INCREMENT,
	NAME VARCHAR(20),
	money DOUBLE
)
INSERT INTO account VALUES(NULL,'tom',1000);
INSERT INTO account VALUES(NULL,'fox',1000);

关于Service与dao的配置

 <!-- service -->
 <bean id="accountService" class="com.baidu.service.AccountServiceImpl">
 <property name="accountDao" ref="accountDao"></property>
 </bean>
 <!-- dao -->
 <bean id="accountDao" class="com.baidu.dao.AccountDAOImpl">
 <!-- 当注入dataSource后,底层会自动创建一个jdbcTemplate -->
 <property name="dataSource" ref="c3p0DataSource"/>
 </bean>

我们让dao去extends jdbcDaoSupport类,这个类中它创建了JdbcTempate,前提是我们需要注入一个dataSource
Sping事务管理机制
Spring事务管理的四个优点:
1.提供一致的对于不同的事务管理的API
2.支持声明式事务管理
3.编程事务管理
4.优秀的整合与Spring的数据访问
Spring事务管理主要提供了三个接口来完成

  1. org.springframework.transaction.PlatformTransactionManager
    这是一个事务管理器,可以来选择相关的平台(jdbc hibernate jpa…)
  2. TransactionDefinition
    它定义事务的一些相关信息 例如 隔离 传播 超时 只读
  3. TransactionStatus
    它主要描述事务具体的运行状态

PlatformTransactionManager
平台事务管理器
在不同的持久化层解决技术它的事务代码不一样
JDBC开发
Connection con=……;
con.setAutoCommit(false);//开启事务
con.rollback();
con.commit();
Hibernate开发
Session session=….;
Transaction t=session.beginTransaction();
t.commit();
t.rollback();
PlatformTransactionManager接口API
在这里插入图片描述
TransactionDefinition
它描述的是事务的定义信息

  • 隔离
  • 传播
  • 超时
  • 只读状态
    事务的四个特性ACID原子性 一致性 隔离性 持久性
    不考虑事务隔离性有什么问题?
    脏读、不可重复读、虚读。
    ISOLATION_DEFUALT它使用后端数据库的默认隔离级别(spring中选项)
    ISOLATION_READ_UNCOMMITTED不能解决问题,会发生脏读、不可重复读、虚读
    ISOLATION_READ_COMMITTED可以解决脏读会产生不可重复读与虚读。
    ISOLATON_REPEATABLE_READ可以解决脏读,不可重复读、解决不了虚读
    ISOLATION_SERIALIZABLE:串行化,可以解决所有问题
    对于不现的数据库,它的底层默认事务隔离级别不一样
    Oracle数据库它默认的是read_committed
    Mysql数据库它默认的是repeatable_read

超时:
默认值是-1它使用的是数据库默认的超时时间
只读:
它的值有两个true/false,如果选择true一般是在我们select操作时
传播:
它解决的是两个被事务管理的方法相互调用问题。它与数据库没关系,是程序内部维护的问题。
PROPAGATION REQUIRED:默认值 两个操作处于同一个事务,如果之前没有事务,新建一个事务
PROPAGATION REQUIRES NEW:两个操作处于不同的事务
PROPAGATION NESTED:它是一种嵌套事务,它是使用SavePoint来实现的。事务回滚时可以回滚到指定的savepoint注意:它只对DataSourceTransactionManager有作用
一下不是经常使用的
PROPAGATION SUPPORTS支持当前事务,如果不存在,就不使用事务
PROPAGATION MANDATORY支持当前事务,如果不存在,抛出异常
PROPAGATION NOT SUPPORTED以非事务运行,如果有事务不存在,挂起当前事务
PROPAGATION NEVER以非事务运行,如果有事务存在,抛出异常

TransactionStatus
它定义了事务状态信息,在事务运行过程中,得到某个时间点的状态
在这里插入图片描述
声明事务管理
事务管理方式
1.编码方案 不建议使用,它具有入侵性。在原有的业务代码基础上去添加事务管理代码
2.声明事务控制,基于AOP对目标进行代理,添加around环绕通知。
这种方案,它不具有侵入性,不需要修改原来的业务代码

基于xml配置声明事务管理方案
第一步:在applicationContext.xml文件中添加aop与tx的名称空间

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

第二步:在applicationContext.xml文件中配置
Spring提供的advice是传统的spring advice
1.声明事务管理

<!-- 配置事务管理器 -->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="c3p0DataSource"></property>
 </bean>

2.配置通知
Spring为我们提供了一个TransactionInterceptor来完成增强

public class TransactionInterceptor extends TransactionAspectSuppot implements MethodInterceptor, Serializable{}

对于这个增强,我们可以使用spring为我们提供的一个标签< tx:advice>来完成操作

<!-- 配置通知 -->
 <tx:advice id="txAdvice" transaction-manager="transactionManager">
 <tx:attributes>
 <!-- name:必须的,对哪些方法进行事务控制
      isolation可选设置事务隔离级别默认DEFAULT
      propagation:可选 设置事务传播 默认值REQUIRED
      timeout 可选 超时时间默认值-1
      read-only 可选默认值是false 如果不是只读,它可以对insert update delete操作,如果是只读不可以。
      rollback-for可选可以设置一个异常,如果产生这个异常,触发事务回滚
      no-rollback-for 可选可以设置一个异常,如果产生这个异常,不会触发事务回滚
       -->
 <tx:method name="account"/>
 </tx:attributes>
 </tx:advice>

3.配置切面
因为使用的是传统的spring的advice,需要使用< aop:advisor>

<!-- 配置切面 -->
 <aop:config>
 <aop:pointcut expression="execution(*com.baidu.service.IAccountService.account(..))" id="txPointcut"/>
 <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
 </aop:config>

基于annotation声明式事务管理
可以使用@Transaction来在类或方法上添加声明式事务管理
注意:需要在applicationContext.xml文件中使用

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

相当于开启注解事务控制
问题:关于xml方式与annotation方式的优缺点?
从简单上来说,使用注解更方便。
使用配置的方案,可以对事务配置进行集中维护。

<tx:method name="get*">
<tx:method name="save*">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值