目录:

  • Part一:回顾java web部分的jdbc、事务、连接池和dbutils工具等 ;
  • Part二:spring的JdbcTemplate使用;
  • Part三:spring的事务处理;

Part一:补充数据库连接,DataSource,事务、连接池等知识;

  1:JDBC部分

    1.1:最基本的jdbc使用:

 1      //要连接的数据库URL
2 String url = "jdbc:mysql://localhost:3306/database名";
3 //连接的数据库时使用的用户名
4 String username = "root";
5 //连接的数据库时使用的密码
6 String password = "root";
7
8 //1.加载驱动
9 Class.forName("com.mysql.jdbc.Driver");//推荐使用这种方式来加载驱动
10 //2.获取与数据库的链接
11 Connection conn = DriverManager.getConnection(url, username, password);
12 //3.获取用于向数据库发送sql语句的statement
13 Statement st = conn.createStatement();
14 String sql = "select id,name,password,email,birthday from users";
15 //4.向数据库发sql,并获取代表结果集的resultset
16 ResultSet rs = st.executeQuery(sql);
    

    1.2:相关类:

    • mysqlUrl的形式:jdbc:mysql://localhost:3306/[databaseName],使用3306端口时,简写为:jdbc:mysql:///[databaseName]   
    • DriverManager类:获取Connection连接
      • DriverManager.getConnection(url, user, password); 
    • Connection类:代表数据库的连接,交互都是通过Connection完成,是最重要的对象;
      • create Statement();preparedStatement(sql)预编译
      • setAutoCommit(false)开启手动提交;commit()事务提交;rollback()回滚;
    • Statement类:向数据库发送sql语句;
      • execute(sql)任一语句;executeQuery(sql)查询sql;executeUpdate(sql)增删改sql
      • addBatch(sql)增加一条批处理;executeBatch()执行批处理;
    • ResultSet类:代表sql执行后的结果,比如查询的返回;
      • getObject(int/String)获取任意类型数据
      • getString(int/String):获取指定类型数据;
      • 滚动获取:next()Previous()等;
    • 释放资源Connection等:
    • PreparedStatement:sql进行预编译,提高执行效率;允许sql中的占位符?,使用preparedstatement.set类型(index,"值")设置值

     1.3:批处理: 

       (1)Statement批处理:statement.addBatch(sql1)....最后statement.executeBatch(),Statement.clearBatch();

       (2)PreparedSatement批处理:只能处理语句相同单参数不同的sql语句,方法同上; 

  2、事务处理:

    事务:逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功;

    2.1:mysql中开启事务:start transaction;开启->crud->commit;(rollback;)提交或回滚;

    2.2:jdbc中的事务:通过Connection设置setAutoCommit(false)、commit()、rollback();

    2.3:事务的四大特性:

      • 原子性:事务中的操作要么全部成功,要么全部失败
      • 异质性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态
      • 隔离性:多个并发事务之间要相互隔离(最麻烦)
      • 持久性:事务一旦被提交,它对数据库中数据的改变就是永久性的

    2.4:不考虑隔离性造成的问题:

      • 脏读:事务A读取事务B未提交的数据
      • 不可重复读:事务A读取数据,多次结果不一样(因为期间事务B提交了事务);
      • 虚读(幻读):事务A读取事务B插入的数据,造成A前后读取数据不一致。

    2.5:隔离性设置:

      • Serializable(串行化):避免全部问题;
      • Repeatable read(可重复读):避免脏读、不可重复读;
      • Read committed(读已提交):避免脏读
      • Read uncommitted(读未提交):最低级,无法避免任何问题;

    2.6:mysql设置隔离性:

      • 默认级别:Repeatable read(可重复读);
      • 查询当前级别:select @@tx_isolation;
      • 设置级别:set transaction isolation level 隔离级别名; 

  3、数据库连接池: 

    Connection资源很珍贵,开销也大,连接池负责管理、分配、释放Connection,允许连接的重复使用;

    3.1:jdbc的DataSource类:这不是连接池,该类只负责批量创建Connection,不负责管理;

        DataSource ds=BasicDataSourceFactory.createDataSource(prop);//创建数据源,prop是load配置文件Properties

        datasource.getConnection()获取Connection ;

    3.2:DBCP开源连接池:使用方法同上,但是DBCP不能自动回收空连接;

    3.3:C3P0开源链接池:Hibernate,Spring框架中常用,能自动回收空闲连接;

       依赖jar包: c3p0-0.9.2-pre1.jar、mchange-commons-0.2.jar;我第一次写spring jdbc就少了后者,囧!

       类目下需配置C3P0的配置文件c3p0-config.xml:jdbc的url,driver、用户名、密码、连接数等;

       使用方式:

      • private static ComboPooledDataSource ds=new ComboPooledDataSource("MySQL")//使用C3P0的命名配置来创建数据源
      • 也可以通过:ds = new ComboPooledDataSource(); ds.setDriverClass("com.mysql.jdbc.Driver"); ....等单独设置连接池大小和驱动,用户密码信息
      • ds.getConection()             

    3.4:JNDI技术:Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需 通过名称检索即可  

  4、其他类与工具类:   

    4.1:通过Connection获取数据库的元数据: 

DatabaseMetaData  Connection.getDatabaseMetaData();//获取database的元数据对象。获取后:getUserName();getURL()获取database的信息;

ParameterMetaData   PreparedStatement.getParameterMetaData() :获取PreparedStatement元数据的对象

ResultSetMetaData    ResultSet. getMetaData() :ResultSet对象元数据的ResultSetMetaData对象

    4.2:Apache 组织的开源 JDBC工具类库dbutils,很多不喜欢hibernate的公司用;

         QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource()); 直接通过qr进行crud;

      ResultSetHandler接口用于处理ResultSet接口;

      搭配ThreadLocal县城本地变量使用; 

Part二:JdbcTemplate的使用

  1.1、JdbcTemplate简介 

    Spring对数据库的操作在jdbc上做了更深层次的封装,使用spring的注入功能,可以将DataSource注册到JdbcTemplate之中

    JdbcTemplate的主要方法:

    • 构造: public JdbcTemplate([DataSource dataSource],[boolean lazyInit]);接收一个DataSource源数据,因因此可以通过spring的配置文件,在管理JdbcTemplate的bean时注入一个DataSource,方便使用 

       1 <context:property-placeholder location="classpath:db.properties"/>
      2 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
      3 <property name="user" value="${jdbc.user}"></property>
      4 <property name="password" value="${jdbc.password}"></property>
      5 <property name="driverClass" value="${jdbc.driverClass}"></property>
      6 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
      7 </bean>
      8
      9 <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
      10 <property name="dataSource" ref="dataSource"></property>
      11 </bean>
    • 方法: execute()、update方法及batchUpdate方法、query方法及queryForXXX方法、call方法 比如:
      • update: int count= jdbcTemplate.update(sql, new Object[]{"王小五",3}); 
      • batchUpdate:
        1 String sql="insert into user (name,deptid) values (?,?)";
        2
        3 List<Object[]> batchArgs=new ArrayList<Object[]>();
        4 batchArgs.add(new Object[]{"caoyc",6});
        5 batchArgs.add(new Object[]{"zhh",8});
        6 batchArgs.add(new Object[]{"cjx",8});
        7
        8 jdbcTemplate.batchUpdate(sql, batchArgs);

  1.2:使用JdbcTemplate读取到实体对象  

    • 读取单个对象:

      @Override
      public User getById(Integer id) {
      String sql="select * from jdbc_user where id=?";
      return super.getJdbcTemplate().queryForObject(sql, new RowMapper<User>() {//内部类重写 mapRow方法
      @Override
      public User mapRow(ResultSet resultSet, int i) throws SQLException {
      User u=new User();
      u.setId(resultSet.getInt("id"));
      u.setName(resultSet.getString("name"));
      return u;
      }
      },id);//别丢
      }
    • 读取对个对象:

       1 public List<User> getAll() {
      2 String sql="select * from jdbc_user";
      3 List<User>list=super.getJdbcTemplate().query(sql, new RowMapper<User>() {
      4 @Override//内部类写法同上,区别在与方法上
      5 public User mapRow(ResultSet resultSet, int i) throws SQLException {
      6 User u=new User();
      7 u.setId(resultSet.getInt("id"));
      8 u.setName(resultSet.getString("name"));
      9 return u;
      10 }
      11 });
      12 return list;
      13 }

Part3:spring的事务管理

【这块我自己还没有完全理清楚,待完善】

ref:CSDN-GrayHJX-Spring事务管理详解

   3.1:JDBC中对事务隔离级别的设置: conn.setTransactionLevel 设置

    • TRANSACTION_NONE JDBC 驱动不支持事务
    • TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读。
    • TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。
    • TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。
    • TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读 

   3.2:Spring事务管理: 

    spring并不直接管理事务,而是提供多种事务管理器,将事务管理委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现;

    通过PlatformTransactionManager接口,Spring为各种平台(JDBC、Hibernate等)提供对应的事务管理器,其具体实现由具体平台负责。

    3.2.1::spring 事务管理核心接口:PlatformTransactionManager 

        通过其 getTransaction(TransactionDefinition definition)方法 根据其指定传播行为返回当前活动的事务或一个新事务。

    3.2.2:TransactionDefinition接口:定义了它自己的传播行为和隔离级别 ,以下为定义的方法;

    • 接口下的方法:

      1     int getPropagationBehavior();//返回传播行为
      2 int getIsolationLevel();//返回隔离级别
      3 int getTimeout();//事务应在多少秒内完成
      4 boolean isReadOnly();//事务是否只读;
      5 String getName();//返回事务名称
    • 7个传播属性:
      1  int PROPAGATION_REQUIRED = 0;//支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是Spring默认的事务的传播
      2 int PROPAGATION_SUPPORTS = 1;//支持当前事务,如果当前没有事务,就以非事务方式执行
      3 int PROPAGATION_MANDATORY = 2;//支持当前事务,如果当前没有事务,就抛出异常。
      4 int PROPAGATION_REQUIRES_NEW = 3;//新建事务,如果当前存在事务,把当前事务挂起。
      5 int PROPAGATION_NOT_SUPPORTED = 4;//以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
      6 int PROPAGATION_NEVER = 5;//以非事务方式执行,如果当前存在事务,则抛出异常
      7 int PROPAGATION_NESTED = 6;//如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作
    • spring事务的隔离级别:
      1     int ISOLATION_DEFAULT = -1;//默认的隔离级别,使用数据库默认的事务隔离级别。
      2 int ISOLATION_READ_UNCOMMITTED = 1;//最低的隔离级别
      3 int ISOLATION_READ_COMMITTED = 2;//保证一个事务修改的数据提交后才能被另外一个事务读取
      4 int ISOLATION_REPEATABLE_READ = 4;//防止脏读,不可重复读
      5 int ISOLATION_SERIALIZABLE = 8;//事务被处理为顺序执行

    3.2.3:各平台的事务管理器:

       

      如上图:(ref:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html

    1. Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
    2. DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager
    • JDBC:使用c3p0生成dataSource数据源bean,使用DataSourceTransactionManager管理事务;

      1 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      2 <property name="dataSource" ref="dataSource"></property>
      3 </bean>
    • Hibernate:Hibernate使用sessionFactory生成session,类似于Connection 。通过HibernateTransactionManager管理实务

      1 <bean id="tranactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
      2 <property name="sessionFactory" ref="sessionFactory"
      3 </bean>
    • Java持久化API事务(JPA):使用spring的JpaTransactionManager处理事务;
      1 <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      2 <property name="sessionFactory" ref="sessionFactory" />
      3 </bean>
    • Java原生API事务:使用JtaTransactionManager管理事务;
      1 <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
      2 <property name="transactionManagerName" value="java:/TransactionManager" />
      3 </bean>              

 3.3:Spring事务管理的方式 :编程式和声明式(基于AOP)

    区别参考自:CSDN-民谊玉超-事务声明声明式事务和编程式事务介绍

    事务实例参考自:cnBlogs-六月的余晖-spring事务管理案例

    实例代码使用idea(2017)编辑;

    3.3.1:编程式事务管理:所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理。管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。    

    3.3.2:声明式事务:管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

     3.3.3:对比:显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。

       声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

    3.3.4:实例:基于jdbc平台(对应的是DataSourceTransactionManager事务管理器)的银行账户aaa向bbb转钱,(aaa的减与bbb的加组成一个事务)

       逻辑图(自己瞎画的,有点乱)

      

     编码式:编码式的实现需要自己编写代码处理事务:此处通过spring提供的transactionTemplate类方便实现,将其注入AccountServiceImpl中,将dataSource注入transactionTemplate,借用其execute方法实现事务操作。需要与操作类进行耦合,不利于拓展。

     声明式:声明式中dao类的bean管理和jdbc事务管理器的配置都是一样的:不同的主要在事务实现配置

 1 <!-- 引入外部属性文件 -->
2 <context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
3 <!--配置c3p0连接池 -->
4 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
5 <property name="driverClass" value="${jdbc.driverClass}"></property>
6 <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
7 <property name="user" value="${jdbc.user}"></property>
8 <property name="password" value="${jdbc.password}"></property>
9 </bean>
10 <!-- 配置业务层 -->
11 <bean id="accountService" class="com.spring.demo2.AccountServiceImpl">
12 <property name="accountDao" ref="accountDao"></property>
13 </bean>
14
15 <!-- 配置DAO层,注入连接池就可以得到jdbc模板-->
16 <bean id="accountDao" class="com.spring.demo2.AccountDaoImpl">
17 <property name="dataSource" ref="dataSource"></property>
18 </bean>
19
20 <!-- 配置事务管理器 -->
21 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
22 <property name="dataSource" ref="dataSource"/>
23 </bean>
    • 2中的配置:

       1  <!--声明式事务管理-->
      2 <!--配置业务层代理-->
      3 <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
      4 <!-- 配置目标对象 -->
      5 <property name="target" ref="accountService"></property>
      6 <!-- 注入事务管理器 -->
      7 <property name="transactionManager" ref="transactionManager"></property>
      8 <!-- 注入事务的属性,可以定位到方法transfer,必须配置-->
      9 <property name="transactionAttributes">
      10 <props>
      11 <prop key="transfer">PROPAGATION_REQUIRED</prop>
      12 </props>
      13 </property>
      14 </bean>
    • 3中的配置:
       1 <!--配置事务的增强-->
      2 <tx:advice id="txAdvice" transaction-manager="transactionManager">
      3 <tx:attributes>
      4 <tx:method name="transfer" propagation="REQUIRED"/>
      5 </tx:attributes>
      6 </tx:advice>
      7
      8 <!--配置切面-->
      9 <aop:config>
      10 <!--配置切点-->
      11 <aop:pointcut expression="execution(* com.spring.demo3.AccountService+.*(..))" id="pointcut1"></aop:pointcut>
      12 <!--配置切面-->
      13 <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"></aop:advisor>
      14 </aop:config>
    • 4中的配置:
      1 <!--开启注解事务,哪个类需要使用事务管理,就在那个类头加上 @Transactional注解即可。-->
      2 <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

    ref:http://www.blogjava.net/robbie/archive/2009/04/05/264003.html总结了五种常用声明式事务管理的配置,可做参考。

目前只理解到这里了~~~,后期再深入学习补充!

<-----------------------------------------------------Ok----------------------------------------------------> 

      

 

spring学习二:jdbc相关回顾以及spring下dao的更多相关文章

  1. spring学习(二) ———— AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  2. 【Java EE 学习 53】【Spring学习第五天】【Spring整合Hibernate】【Spring整合Hibernate、Struts2】【问题:整合hibernate之后事务不能回滚】

    一.Spring整合Hibernate 1.如果一个DAO 类继承了HibernateDaoSupport,只需要在spring配置文件中注入SessionFactory就可以了:如果一个DAO类没有 ...

  3. Spring学习详解(1)——Spring入门详解

    一:spring的基本用法: 1,关于spring容器: spring容器是Spring的核心,该 容器负责管理spring中的java组件, ApplicationContext ctx  = ne ...

  4. Spring学习(一)--简化Java开发,认识Spring

    一.传统Java开发弊端 在传统的开发之中,任何一个有实际意义的应用都会由两个或更多的类所组成,这些类之间相互协调来完成特定的业务逻辑,按照传统的做法,每个对象负责管理与自己相互协作的对象(即他所依赖 ...

  5. Spring学习之旅(八)Spring 基于AspectJ注解配置的AOP编程工作原理初探

    由小编的上篇博文可以一窥基于AspectJ注解配置的AOP编程实现. 本文一下未贴出的相关代码示例请关注小编的上篇博文<Spring学习之旅(七)基于XML配置与基于AspectJ注解配置的AO ...

  6. Spring学习笔记(1)——初识Spring

    一.Spring是什么       通常说的Spring其实指的是Spring Framework,它是Spring下的一个子项目,Spring围绕Spring Framework这个核心项目开发了大 ...

  7. Spring学习之——手写Mini版Spring源码

    前言 Sping的生态圈已经非常大了,很多时候对Spring的理解都是在会用的阶段,想要理解其设计思想却无从下手.前些天看了某某学院的关于Spring学习的相关视频,有几篇讲到手写Spring源码,感 ...

  8. Spring学习之旅(四)Spring工作原理再探

    上篇博文对Spring的工作原理做了个大概的介绍,想看的同学请出门左转.今天详细说几点. (一)Spring IoC容器及其实例化与使用 Spring IoC容器负责Bean的实例化.配置和组装工作有 ...

  9. Spring学习8-用MyEclipse搭建SSH框架 Struts Spring Hibernate

    1.new一个web project. 2.右键项目,为项目添加Struts支持. 点击Finish.src目录下多了struts.xml配置文件. 3.使用MyEclipse DataBase Ex ...

随机推荐

  1. 如何结合phpstorm配置在docker中的xdebug

    作为一个资深的php开发者,我在之前的一篇文章里面也讲了如何搭建lnmp的docker镜像,这里不再赘述.在基于镜像运行容器中我也安装了xdebug,于是考虑用phpstorm来配置xdebug. 使 ...

  2. springboot项目 @Scheduled注解 实现定时任务

    使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式: 一.基于注解(@Scheduled) 二.基于接口(SchedulingConfigurer) 前者相信大家都很熟悉,但是实 ...

  3. 安装配置ingress-nginx支持https访问

    说明: ​ 1.k8s版本:v1.23: ​ 2.内网测试环境1台master,2台node节点,使用 DaemonSet+HostNetwork+nodeSelector 方式部署 ingress- ...

  4. RESTful风格了解

    最近在学习springboot,一直听到一个词叫RESTful风格,今天找了一下书了解了一番.spring mvc除了支持json数据交互外,还支持RESTful风格 RESTful也称为REST(r ...

  5. 什么是闭包?(python)

    闭包,又称闭包函数或闭合函数,和嵌套函数类似.不同之处在于,闭包函数的外部函数返回的不是一个具体的值,而是一个函数.一般情况下,返回的函数会赋值给一个变量,便于反复调用. def outer(out) ...

  6. Java课程设计---浏览学生(表格的使用)

    1.创建显示表格的窗体 package com.student.view; import java.awt.EventQueue; import javax.swing.JFrame; import ...

  7. 阿里云 elk 搭建

    1.logstash通过redis收集日志. logstash > redis>logstash  >es k8s日志挂载 tong sudo umount -t glusterfs ...

  8. Chapter02 Java概述

    Chapter02 Java概述 目录 Chapter02 Java概述 2.1 什么是程序 程序: 2.2 Java的重要特点 2.3 Java 运行机制及运行过程 2.3.1 Java 语言的特点 ...

  9. JZ-037-数字在排序数组中出现的次数

    数字在排序数组中出现的次数 题目描述 统计一个数字在升序数组中出现的次数. 题目链接: 数字在排序数组中出现的次数 代码 /** * 标题:数字在排序数组中出现的次数 * 题目描述 * 统计一个数字在 ...

  10. 流程控制、if、elif、else,whilie、break、continue的使用

    今日内容 流程控制理论 if判断 while循环 流程控制概念 流程控制就是控制事物的执行流程 执行流程的分类 顺序结构 从上往下依次执行,代码运行流程图如下 分支结构 根据某些条件判断做出不同的运行 ...