Spring框架学习第三天

Spring DAO

  • DAO(Data Access Object)数据访问对象
  • Spring DAO为整合JDBC提供了封装,简化了DAO组件的编写
  • Spring DAO提供了AOP模式的事务处理
  • Spring DAO提供了统一的异常处理层次,它包装的异常类型DataAccessException继承自RuntimeException无须显式的捕获

Spring DAO所做的工作

  1. 对JDBC的操作进行封装,简化了JDBC的操作
  2. 对JDBC的事务进行了AOP模式的封装,简化了事物的管理和操作
  3. 对数据库访问中的异常,由原来的检查异常,封装成了继承RunTimeException的非检查异常DataAccessException

JDBCTemplate

这个类负责加载驱动、获取连接、获取执行环境和释放资源
我们只需要关心sql的编写和数据的处理

如何获取JDBCTemplate

最直接的是继承JDBCDAOSupport这个类
如果不继承JDBCDAOSupport则需要自己注入模版

使用继承的方式
  1. 准备一张表放入数据
  2. 写一个产品的接口,接口中定义一个查询产品数据的方法
  3. 先导入ioc,aop,dao对应的jar包,写一个接口的实现类继承JDBCDAOSupport并实现接口
  4. 使用模板和模板对应的方法完成数据量的查询
  5. 测试dao实现类,看是否能获取到对应的数据

以继承JDBCDAOSupport的方式查询数据

  • 建立一张银行账户表 并且建立对应的序列,最后使用序列作为主键值插入几条数据
  • 建立一个项目拷贝ioc,aop,连接池,数据库驱动包以及Spring容器对应的配置文件,开启组件扫描和注入dataSource
  • 写一个接口定义一个查询数据量的方法
  • 写一个接口的实现类,继承JDBCDAOSupport,加标注@Repository并且注入dataSource,这个dataSource要定义在xml中并且传递给父类
    使用模板完成数据查询
  • 写一个测试类测试功能

根据银行卡号查询一个银行账户

  • 建立表和序列以及插入数据
  • 根据表设计实体类
  • 在接口加一个根据卡号查询账户的方法
  • 在实现类中使用模板来完成功能(使用模板完成功能时,需要用到RowMapper的实现类)
  • 测试

根据卡号和密码查询一个银行账户

  • 建立表和序列以及插入数据
  • 根据表设计实体类
  • 在接口加一个根据卡号和密码查询账户的方法
  • 在实现类中使用模板来完成功能(使用模板完成功能时,需要用到RowMapper的实现类)
  • 测试

查询对象列表

给银行账户表增加数据

  1. 接口中增加一个方法,传入一个银行账户对象进来,然后把这些数据传入数据库
  2. 实现类中实现这个方法
  3. 测试

Spring整合JDBC

JdbcTemplate提供了以下的主要方法

  • queryForInt()
  • queryForObject()
  • query()
  • update()
  • execute()

总结JDBCTemplate的方法

queryForInt查询数据的数据量
queryForObject查询数据的数据量,也可以查询单个对象(使用到RowMapper)
query查询数据列表(也会用到RowMapper)
update用来完成增删改查
execute一般用来执行DDL(建表、删表、改表),用得比较少,但是有相关的业务还是得会!

不继承JDBCDAOSupport的方式

就需要我们自己注入JDBCTemplate

使用模板和不使用模板的区别

  1. 继承JDBCDAOSupport不继承JDBCDAOSupport

  2. 注入的方式不同,例如:

    使用模板

    @Autowired
    public BankAccountDaoImp(DataSource dataSource) {
        super.setDataSource(dataSource);
    }
    

    不使用模板

    @Override
    public int getBankAccountCount() {
        String sql = "select count(*) from BANK_ACCOUNT_2018_11";
        return jdbcTemplate.queryForObject(sql, Integer.class);
    }
    

Spring中的事务

把多个sql(dml,增删改)操作看成一个逻辑整体,这些语句要求一起成功或者一起失败

特性
  • 原子性(事务中的语句是一个整体不可再分)
  • 一致性(事务中的语句状态要保持一致)
  • 隔离性(隔离级别:脏读、幻读、不可重复读)

详细解释隔离级别

脏读:一个事务读取到了另外一个事务没有提交的数据
不可重复读:一个事务在开始时读取了一份数据,在事务的操作过程中,另外一个事务对你读取的那份数据进行了修改(改动),并进行了提交,当第一个事务再次读取数据时,发现数据发生了改变。
幻读:一个事务在事务开始时对所有的数据进行了统计 在统计过程中数据发生了增加数据 再次统计所有数据时,数据改变了

为了解决三大读问题,引入四个隔离级别
读未提交 读提交 可重复读 序列化
1 2 3 4
持久性

Spring中事务的实现

  1. 编程式事务(使用大量Java代码完成事务)
  2. 声明式事务(基于AOP编程)

Spring中声明式事务的实现

Spring声明式事务的优势
通过Spring的配置,对事务管理而不是在源代码进行直接编码,解除了事务管理和代码的耦合,可以随时从Spring容器中进行删除

声明式事务的实现步骤
  1. 开启组件扫描和声明式事务
<!--开启组件扫描-->
<context:component-scan base-package="com.dao"/>

<!--开启声明式事务 transaction-manager就是事务管理器的意思,proxy-target-class如果是false代表jdk的代理机制(必须要求你的这个类实现接口),如果是true代表使用cglib的动态代理-->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
  1. 配置事务管理器和数据源
<!--数据源配置文件-->
<util:properties id="db" location="classpath:db.properties"/>

<!--数据源对象-->
<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="#{db.driverClassName}"/>
    <property name="url">
        <value>#{db.url}</value>
    </property>
    <property name="username" value="#{db.username}"/>
    <property name="password" value="#{db.password}"/>
</bean>

<!--创建事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="ds"></property>
</bean>
  1. 在需要事务管理的方法或者类上加@Transaction标注

注意:实际上事务管理器可以不动任何源代码!

@Transactional注解标记有以下属性,在使用时可以根据需要做特殊设定。

  • propagation:设置事务传播
  • isolation:设置事务隔离级别
  • readOnly:设置为只读,还是可读写
  • rollbackFor:设置遇到哪些异常必须回滚针对检查异常
  • noRollbackFor:设置遇到哪些异常不回滚针对运行异常
    Oracle只支持isolation的两个级别:读提交和幻读(序列化)
    任何的RuntimeException将触发事务回滚,但是任何CheckedException将不触发事务回滚

只有service有资格加事务标注

二次修订版

文件说明

  • Spring-jdbc.xml -> 配置文件

Spring dao

Spring dao所做的工作

  1. 对JDBC的操作进行封装,简化了JDBC的操作
  2. 对JDBC的事务进行了AOP模式的封装,简化了事物的管理和操作
  3. 对数据库访问中的异常,由原来的检查异常,封装成了继承RunTimeException的非检查异常DataAccessException

JDBCTemplate

这个类负责加载驱动获取连接获取执行环境释放资源

我们就只需要关心sql语句的编写数据的处理

如何获取JDBCTemplate

  1. 最直接的是继承JDBCDAOSupport这个类
  2. 如果不继承JDBCDAOSupport则需要自己注入模版

使用继承的方式得到模板类

  1. 准备一张表放入数据
  2. 写一个产品的接口,接口中定义一个查询产品数据的方法
  3. 先导入ioc,aop,dao对应的jar包,写一个接口的实现类继承JDBCDAOSupport并实现接口
  4. 使用模板和模板对应的方法完成数据量的查询
  5. 测试dao实现类,看是否能获取到对应的数据

在3注入一个dataSource

测试得到xx_user表的数据

表里的数据如下:

idunameupassuemail
0admin1234562301927217@qq.com
1test123456wlmno1@vip.qq.com
UserDao接口
package com.dao;

/**
 * @author biuaxia
 */
public interface UserDao {
    /**
     * @return 表中的所有用户数量
     */
    int getUserCount();
}
UserDaoImp实现类
package com.dao;

import com.bean.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * Class Describe:
 *
 * @author biuaxia
 * @date 2018/11/13
 * @time 19:39
 */
@Repository("userdao")
public class UserDaoImp extends JdbcDaoSupport implements UserDao {

    /**
     * 注入一个dataSource
     */
    /**
     * 不能直接使用private DataSource dataSource注入
     * 因为JdbcDaoSupport中的dataSource为final,不能通过set注入
     * 我们通过自定义方法名进行注入
     * 方法如果不改名就会找MyDataSource这个东西,不指定名字会比较危险
     */
    @Resource(name = "dataSource")
    public void setMyDataSource(DataSource dataSource) {
        //把注入的dataSource传递给父类
        super.setDataSource(dataSource);
    }

    @Override
    public int getUserCount() {
        //利用模板调用对应的api完成查询
        String sql = "select count(*) from XX_USER";
        /*return super.getJdbcTemplate().queryForInt(sql);*///此方法已过时
        return super.getJdbcTemplate().queryForObject(sql, Integer.class);
    }

    public static void main(String[] args) {
        ApplicationContext app = new ClassPathXmlApplicationContext("spring-jdbc.xml");
        UserDao dao = app.getBean("userdao", UserDao.class);
        System.out.println(dao.getUserCount());
    }
}
spring-jdbc.xml详细配置
<?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:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jpa="http://www.springframework.org/schema/data/jpa"
       xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
		http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
		http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
    <!--开启组件扫描-->
    <context:component-scan base-package="com.dao"/>
    <!--引入外部db.properties-->
    <util:properties id="db" location="classpath:db.properties"></util:properties>
    <!--配置dataSource-->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="#{db.driverClassName}"></property>
        <property name="url" value="#{db.url}"></property>
        <property name="username" value="#{db.username}"></property>
        <property name="password" value="#{db.password}"></property>
    </bean>
</beans>
db.properties
driverClassName=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
username=system
password=123456
运行UserDaoImp的主方法即可
2

Process finished with exit code 0

查询银行账户表中的数据量

  • 建立一张银行账户表 并且建立对应的序列,最后使用序列作为主键值插入几条数据
  1. 建立一个项目拷贝ioc,aop,连接池,数据库驱动包以及Spring容器对应的配置文件,开启组件扫描和注入dataSource
  2. 写一个接口定义一个查询数据量的方法
  3. 写一个接口的实现类,继承JDBCDAOSupport,加标注@Repository并且注入dataSource,这个dataSource要定义在xml中并且传递给父类(要自定义set方法)
  4. 使用模板完成数据查询使用模板完成数据查询,写一个测试类测试功能
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值