day04_Spring JdbcTemplate&声明式事务

在这里插入图片描述
##一.jdbcTemplate的使用
1、jdbcTemplate的介绍
jdbc — dbutils – jdbcTemplate(spring 提供) – mybatis(主流) – spring data jpa(趋势)

2、数据源配置
jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring331
jdbc.username=root
jdbc.password=root

applicationContext.xml (引入spring-context才有提示)

<!--引入外部属性文件 引入spring-context才有提示-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>

a. c3p0数据源
依赖

	<!--c3p0数据源-->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>

配置

<!--配置c3p0数据源-->
<bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="jdbcUrl" value="${jdbc.url}"></property>
    <property name="driverClass" value="${jdbc.driver}"></property>
    <property name="user" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

b. dbcp数据源
依赖

	<!--dbcp数据源-->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>

配置

<!--dbcp数据源-->
<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="url" value="${jdbc.url}"></property>
    <property name="driverClassName" value="${jdbc.driver}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

c. spring jdbc 自带数据源,包含了JdbcTemplate对象
依赖

	<!--spring自带数据源 "spring的jar都引入同一个版本 不能混用"-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

配置

<!--spring自带数据源-->
<bean id="springDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driver}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

3、jdbcTemplate的CRUD
可以发现,jdbcTemplate和dbutils没有太大区别,一类jdbcAPI,同类:配置、写法和作业功能几乎完全雷同

queryRunner(datasource)---->提供API操作数据
jdbcTemplate.set(datasource)---->提供API操作数据库

Account.java

public class Account {
private String name;
private int money;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getMoney() {
    return money;
}

public void setMoney(int money) {
    this.money = money;
}

public Account() {
}

public Account(String name, int money) {
    this.name = name;
    this.money = money;
}

@Override
public String toString() {
    return "Account{" +
            "name='" + name + '\'' +
            ", money=" + money +
            '}';
}

}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>



<context:property-placeholder location=“jdbc.properties”></context:property-placeholder>






<!--dbcp数据源-->
<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="url" value="${jdbc.url}"></property>
    <property name="driverClassName" value="${jdbc.driver}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

<!--spring自带数据源-->
<bean id="springDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driver}"></property>
    <property name="url" value="${jdbc.url}"></property>
    <property name="username" value="${jdbc.username}"></property>
    <property name="password" value="${jdbc.password}"></property>
</bean>

<!--各数据源就名字上有点区别 用起来没有任何区别-->

<!--创建jdbcTemplate模板对象 和dbutils的queryRunner一样 一种jdbc工具类-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="springDataSource"></property>
</bean>
<!--可以直接用jdbcTemplate操作数据库 test类相当于daoimpl类-->

TestJdbcTemplate.java

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(“classpath:applicationContext.xml”)
public class JdbcTemplateCURDTest {
@Autowired
private JdbcTemplate jdbcTemplate;

@Test
//修改方法测试
public void testUpdate() {
    int row = jdbcTemplate.update("update account set money = ? where name = ?", 10000, "Tom");
    System.out.println(row);
}

@Test
//删除方法测试
public void testDelete() {
    int row = jdbcTemplate.update("delete from account  where name = ?", "Tom");
    System.out.println(row);
}

@Test
//查询所有测试
public void testQuerryAll() {
    List<Account> accountList = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
    System.out.println(accountList);
}

@Test
//查询单个测试
public void testOne() {
    Account tom = jdbcTemplate.queryForObject("select * from account where name= ?", new BeanPropertyRowMapper<Account>(Account.class), "tom");
    System.out.println(tom);
}

@Test
//查询聚合函数测试
public void testCount() {
    Integer num = jdbcTemplate.queryForObject("select count(*) from account ", Integer.class);
    System.out.println(num);
}

}

4、在dao中使用jdbcTemplate方法一 (好用★)
a、applicationContext.xml中创建模板

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="springDataSource"></property>
</bean>

b、dao层中注解注入后直接使用模板对象
@Repository
public class AccountDaoImpl implements AccountDao {

@Autowired
JdbcTemplate jdbcTemplate;

@Override
public List<Account> findAll() {
    String sql="select * from account";
    List<Account> accountList = jdbcTemplate.query(sql, new AccountRowMapper());
    return accountList;
}

}

5、在dao中使用jdbcTemplate方法二 (麻烦 少用)
a、在dao实现类中继承接口JdbcDaoSupport类
getJdbcTemplate直接获取jdbc模板

public class AccountDaoImpl2 extends JdbcDaoSupport implements AccountDao {

@Override
public List<Account> findAll() {
    String sql="select * from account";
    List<Account> accountList = getJdbcTemplate().query(sql, new AccountRowMapper());
    return accountList;
}

}

b、所有的dao对象需要在xml中创建,需要通过set方法(属性)注入数据源对象
因为setDataSource方法写在父类中,无法框架本身的代码中加个@Autowired注解(注解方法创建dao的话只能注解注入属性),因此只能在xml中注入属性值

<!--子类继承父类属性 直接往accountDaoImpl2中注入即可-->
<bean id="accountDao" class="cn.ahpu.dao.impl.AccountDaoImpl2">
    <property name="dataSource" ref="springDataSource"></property>
</bean>

1
2
3
4
5
第一种在 Dao 类中定义 JdbcTemplate 的方式,适用于所有配置方式( xml 和注解都可以)。
第二种让 Dao 继承> JdbcDaoSupport 的方式,只能用于基于 XML 的方式,注解用不了。

##二、Spring 中的事务控制
在这里插入图片描述
1、spring事务控制的api介绍–事务管理类
真正管理事务的对象
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 SpringJDBC 或 iBatis 进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager 使用Hibernate 版本进行持久化数据时使用

2、事务的特性
a、事务的四个特性
原子性: 不可再分割
隔离性: 事务之间的隔离级别
一致性: 要么全部完成,要么全部不完成
持久性: 一旦提交持久化到数据中

b、隔离级别
1、读未提交:read uncommited
产生的问题:脏读,幻读,不可重复读
脏读:读到了未提交的数据
不可重复读:
幻读(虚读):
2、读已提交:read commited
产生的问题:幻读,不可重复读
解决的问题:脏读
3、重复读: repeatable read
产生的问题:幻读
解决的问题:脏读,不可重复读
4、串行化(序列化): serializable
产生的问题:null
解决的问题: 所有的问题
隔离级别最高,效率最低

c、数据库的支持的隔离级别 – 一般情况下选择都是默认的隔离级别
mysql:支持:read uncommited read commited repeatable read serializable 支持三个隔离级别
默认的隔离级别:repeatable read
Oracle支持:read commited serializable read only(只读)
默认的隔离级别:read commited

3、事务的传播
a. 掌握
增删改: REQUIRED: 必要的: 如果没有事务,则新建一个事务,如果有事务,加入这个事务当中, spring指定为默认值
查询: SUPPORTS: 支持的: 如果没有事务,非事务执行,如果有事务,加入这个事务当中

b. 了解
MANDATORY: 可以使用当前的事务,如果没有事务,抛出异常
REQUERS_NEW: 新建一个事务,如果存在事务,则挂起事务
NOT_SUPPORTED: 必须非事务执行,如果有事务,则挂起事务
NEVER: 非事务执行,如果存在事务,抛出异常
NESTED: 有事务,嵌套执行,没有事务,执行REQUIRED

4、是否为只读的事务
a.如果是查询,则为只读的事务 readOnly=true
b.如果是增删改,则为非只读的事务,readOnly=false

5、基于xml声明式事务管理(配置文件)(重点★★)(推荐)
a. 编程式事务管理:在业务层写了事务技术代码
b. 声明式事务管理:在配置文件声明事务对象,管理事务,业务层中没有任何事务代码
引入依赖:
pom.xml

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.9</version>
    </dependency>
    <!--spring事务管理jar-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>

2) 编写配置文件
applicationContext.xml

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <!--注入数据源:数据存在于某次数据库连接中-连接存在于连接池(数据源)中-->
    <property name="dataSource" ref="springDataSource"></property>
</bean>

<!--事务的增强:过滤方法是否需要拦截
    advice 增强  注意名称空间是tx不是cache
    有些查询类方法没有事务也行 配置一下提高效率
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--增强:方法的过滤-->
    <tx:attributes>
        <!--指定需要拦截的方法
            isolation:隔离级别,一般选择默认的
            propagation:传播的行为
            read-only:是否为只读事务 查询只读 增删改非只读
            timeout="-1" 用不超时
        -->
        <!--<tx:method name="insert*"  />-->
        <!--<tx:method name="add*"  />-->
        <!--<tx:method name="update*"  />-->
        <!--<tx:method name="del*"  />-->
        <!--<tx:method name="delete*" />&lt;!&ndash;全部都是默认配置 不需要写 下面留着方便看&ndash;&gt;-->
        <!--<tx:method name="save*" isolation="DEFAULT" propagation="REQUIRED" read-only="false" timeout="-1"/>-->
        <!--&lt;!&ndash;查询 name用通配符 和模糊查询一样 以find开头的都匹配&ndash;&gt;-->
        <!--<tx:method name="find*" propagation="SUPPORTS" read-only="true" />-->
        <!--<tx:method name="select*" propagation="SUPPORTS" read-only="true" />-->
        <!--<tx:method name="query*" propagation="SUPPORTS" read-only="true" />-->
        <!--<tx:method name="get*" isolation="DEFAULT" propagation="SUPPORTS" read-only="true" timeout="-1"/>-->

        <!--配置方式二-->
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        <tx:method name="get*" propagation="SUPPORTS" read-only="true"></tx:method>
        <tx:method name="query*" propagation="SUPPORTS" read-only="true"></tx:method>
        <tx:method name="select*" propagation="SUPPORTS" read-only="true"></tx:method>
        <!--其他配置统一为-->
        <tx:method name="*" propagation="REQUIRED" read-only="false"></tx:method>

    </tx:attributes>
</tx:advice>


<!--aop的配置
    切面=切入点+通知(增强)
-->
<aop:config>
    <!--切面配置
        advice-ref:通知关联对象(本质上是transactionManager txAdvice对其进行了进一步封装加强)
        pointcut:切入点
    -->
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.ahpu.service.impl.*.*(..))"></aop:advisor>
</aop:config>

业务层
业务层不需要任何事务管理,只需要提供业务代码即可

6、基于注解的配置(重点 一样傻瓜式简单)
a. 引入依赖
与xml完全一致

b. 配置文件

<!--创建事务管理器对象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <!--注入数据源:数据存在于某次数据库连接中-连接存在于连接池(数据源)中-->
    <property name="dataSource" ref="springDataSource"></property>
</bean>

<!--关联事务管理器对象-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

<!--开启aop的注解:自动代理 或许不需要-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

c. 业务层
在类上标记注解:@Transactional, 类中所有的方法都会使用事务管理
在方法上标记注解:@Transactional:只有该方法按照事务执行

d.属性介绍(类似配置文件方式的txAdvice的配置)
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, readOnly =
false,timeout = -1)

事务处理注解方式简单总结:3个配置,一个注解 ,万事大吉。
也有人喜欢xml方式:不需要每次到业务层加@Transactional了
事务处理xml方式简单总结:3个配置,万事大吉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值