目录:

  • 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. 聊聊几个阿里 P8、P9 程序员的故事

    大家好,我是对白. 阿里 P8 程序员年薪百万已经是公开的秘密了,有人关心他们年薪百万,而我更加关注阿里这些 P8.P9 程序员的成长故事,在聊这些大牛的故事之前,跟大家稍微简单聊下阿里技术人等级制度 ...

  2. validator参数校验

    目录 validator参数校验 validator参数校验 type Req struct { Sn string `json:"sn" binding:"requir ...

  3. 「BUAA OO Pre」 Pre 2总结回顾概览

    「BUAA OO Pre」 Pre 2总结回顾概览 目录 「BUAA OO Pre」 Pre 2总结回顾概览 Part 0 前言 写作背景 定位 您可以在这里期望获得 您在这里无法期望获得 对读者前置 ...

  4. 【Elastic-2】SpringBoot整合ELK、SpringBoot写ES

    ELK相关TODO 快速开始文档(https://www.cnblogs.com/lbhym/p/15934416.html) SpringBoot整合ELK ELK接入Kafka(待Kafka快速开 ...

  5. kali linux更新msf 报错Unable to find a spec satisfying metasploit-framework (>= 0) in the set. Perhaps the解决办法

    首先换更新源 :vim  /etc/apt/sources.list deb http://mirrors.ustc.edu.cn/kali kali-rolling main non-free co ...

  6. 【windows 访问控制】七、window 访问控制编辑器(Access Control Editor)

    window 访问控制编辑器(Access Control Editor) 右键(文件.目录.程序)>选择属性>安全>高级   进入访问控制编辑器

  7. (转载)虚拟化(3):os调度策略。

    转自:https://zhuanlan.zhihu.com/p/38046313 这一章主要是介绍几个简单的调度器策略.内容比较简单,就简单汇总下. 首先我们对现有的计算机环境有如下几个假设: 1.每 ...

  8. Go select 死锁引发的思考

    Go select 死锁引发的思考 https://mp.weixin.qq.com/s/Ov1FvLsLfSaY8GNzfjfMbg一文引发的延续思考 上文总结 总结一 package main i ...

  9. git报错error: RPC failed; HTTP 500 curl 22 The requested URL returned error: 500

    报错 $ git push; Enumerating objects: 1002, done. Counting objects: 100% (1002/1002), done. Delta comp ...

  10. pandas连接数据库

    项目中使用pandas方法读取数据库数据可能用到的方法 使用pandas连接数据库 例如 mysql_conn = pymysql.connect(host='172.28.*.***', port= ...