JDBC:

* JDBC概念:Java DataBase Connectivity(Java数据库连接)

SUN公司提供的一组连接数据库API.

* JDBC开发步骤:

* 1.注册驱动.

* 2.获得连接.

* 3.执行SQL.

* 4.释放资源.

* JDBC入门案例:

* JDBC的API详解:

* DriverManager:

* 管理驱动:

* Class.forName(“com.mysql.jdbc.Driver”);

* 获得连接:

* getConnection(String url,String username,String password);

* Connection:

* 创建执行SQL的对象:

* createStatement();

* prepareStatement(String sql);

* 管理事务:

* setAutoCommit(boolean flag);

* commit();

* rollback();

* Statement:

* 执行SQL语句

* executeQuery(String sql);

* executeUpdate(String sql);

* execute(String sql);

* 执行批处理

* addBatch(String sql);

* executeBatch();

* clearBatch();

* ResultSet:

* 结果集:

* 默认只能向下不可以修改.

* 多条记录:

while(rs.next()){

rs.getXXX();

}

* 一条记录:

if(rs.next()){

}

* 滚动结果集:(了解)

JDBC开发CRUD的操作:

* 资源释放:

* Connection的资源是非常稀有的,应该做到晚创建,早释放!

* 抽取工具类:

* 提取了一个配置文件db.properties

EE开发中的DAO模式:

* DAO模式主要用来解决持久层的问题!

* 操作数据库!

DAO模式编写了一个登陆案例:

* 页面---->Servlet---->UserService---->UserDao

* 演示了SQL注入漏洞:

* 解决:

* PreparedStatement:对SQL进行预编译!

大文件读写:

批处理:

1.1 JDBC中事务管理:

1.1.1 事务:

事务:指的是逻辑上一组操作!一组操作要么全都成功,要么全都失败!

1.1.2 MYSQL数据库中操作事务

MYSQL的数据库的事务是自动提交的!!!Oracle不是自动提交的!!!

MySQL数据库,写一个SQL就是一个事务!!!

创建一个表:

create database day18;

use day18;

create table account(

id int primary key auto_increment,

name varchar(20),

money double

);

insert into account values (null,'美美',10000);

insert into account values (null,'小边',10000);

insert into account values (null,'冠希',10000);

insert into account values (null,'白鸽',10000);

insert into account values (null,'小白',10000);

MYSQL中管理事务:

有两种方式管理事务:

一、使用命令方式:

* start transaction; --- 开启事务

* commit; --- 事务提交

* rollback; --- 事务回滚

二、设置MYSQL数据库参数:

* show variables like '%commit%';

+--------------------------------+-------+

| Variable_name | Value |

+--------------------------------+-------+

| autocommit | ON |

| innodb_commit_concurrency | 0 |

| innodb_flush_log_at_trx_commit | 1 |

+--------------------------------+-------+

* 设置自动提交参数为OFF(0) ON(1)

set autocommit = 0;

1.1.3 JDBC中使用事务:
JDBC的事务

通过Connection对象中的

* setAutoCommit(false);

* commit();/rollback();

案例:

@Test

// 冠希给美美转账 1000元

public void demo1(){

Connection conn = null;

PreparedStatement stmt = null;

try{

// 获得连接

conn = JDBCUtils.getConnection();

// 管理事务:事务不是自动提交!

conn.setAutoCommit(false);

// 编写一个SQL语句

String sql = "update account set money = money + ? where name = ?";

// 预编译SQL

stmt = conn.prepareStatement(sql);

// 设置参数:

// 扣去冠希的1000元

stmt.setDouble(1, -1000);

stmt.setString(2, "冠希");

stmt.executeUpdate();

// 如果现在没有事务的保证:当扣除冠希的1000元之后,会发生什么情况?

// 这个时候 冠希的钱就被扣除了,但是美美没有收到钱!!!

// 所以多条SQL要由事务保证:事务就是保证逻辑上的一组操作要么全都成功,要么全都失败!

int a = 10 / 0;

// 为美美增加1000元

stmt.setDouble(1, 1000);

stmt.setString(2, "美美");

stmt.executeUpdate();

// 提交事务:

conn.commit();

}catch(Exception e){

// 异常发生了:

try {

conn.rollback();

} catch (SQLException e1) {

e1.printStackTrace();

}

e.printStackTrace();

}finally{

JDBCUtils.release(stmt, conn);

}

}

JDBC事务的保存点:(了解)

保存点的作用:回滚的时候不用回滚到最初始的状态!!!

Connection中有

* setSavepoint() --- 设置一个保存点

* rollback(SavePoint savePoint); --- 事务回滚到保存点的位置

@Test

// 小边跟美美说你借我1w,设置一个保存点,我还你10w.但是小边的账号余额不足.回滚到保存点的位置!

public void demo2(){

Connection conn = null;

PreparedStatement stmt = null;

ResultSet rs = null;

try{

// 获得连接

conn = JDBCUtils.getConnection();

// 开启事务:

conn.setAutoCommit(false);

// 编写一个sql语句.

String sql = "update account set money = money + ? where name = ?";

// 预编译SQL

stmt = conn.prepareStatement(sql);

// 扣除美美的1w元

stmt.setDouble(1, -10000);

stmt.setString(2, "美美");

stmt.executeUpdate();

// 给小边增加1w元

stmt.setDouble(1, 10000);

stmt.setString(2, "小边");

stmt.executeUpdate();

// 设置一个保存点

Savepoint savePoint = conn.setSavepoint();

// 小边还给美美10w

stmt.setDouble(1, -100000);

stmt.setString(2, "小边");

stmt.executeUpdate();

stmt.setDouble(1, 100000);

stmt.setString(2, "美美");

stmt.executeUpdate();

sql = "select * from account where name = ?";

stmt = conn.prepareStatement(sql);

// 设置参数

stmt.setString(1, "小边");

rs = stmt.executeQuery();

if(rs.next()){

if(rs.getDouble("money")<0){

conn.rollback(savePoint);

System.out.println("上当了!!!");

}

}

// 事务提交

conn.commit();

}catch(Exception e){

try {

conn.rollback();

} catch (SQLException e1) {

e1.printStackTrace();

}

e.printStackTrace();

}finally{

JDBCUtils.release(rs, stmt, conn);

}

}

1.1.4 事务的特性:(面试)

原子性:

* 强调的是事务的不可分割!

一致性:

* 事务执行的前后,数据的完整性保持一致!

隔离性:

* 一个事务的执行,不应该受到另一个事务的打扰!

持久性:

* 事务执行结束!数据就永久的保存数据库中!

如果不考虑事务的隔离性:引发哪些问题?

* 引发三种读的问题.

* 脏读 :一个事务读到了另一个事务未提交的数据!!!

* 不可重复读 :一个事务读到了另一个事务已经提交数据(另一个事务中做的是update操作),导致多次查询结果在一个事务中不一致!

* 虚读(幻读) :一个事务读到了另一个事务已经提交数据(另一个事务中做的是insert操作),导致在事务中做的统计的结果不一致!!

* 如何解决问题?

* 数据库提供了四个隔离级别解决三种读问题!!!

* read uncommitted :未提交读.那么脏读、不可重复读、虚读都是有可能发生!!

* read committed :已提交读.避免脏读。但是不可重复读和虚读是有可能发生!!

* repeatable read :重复读.避免脏读、不可重复读。但是虚读是有可能发生的!!

* serializable :串行的.避免脏读、不可重复读、虚读的发生!!

* 安全性:

read uncommitted < read committed < repeatable read < serializable

* 效率性:

read uncommitted > read committed > repeatable read > serializable

***** 数据库中使用的时候一般不会采用最低和最高的!!!

* MYSQL中使用的是repeatable read Oracle中read committed

通过命令查看事务的隔离级别:

* select @@tx_isolation;

设置数据库隔离级别:

* set session transaction isolation level 隔离级别;

演示脏读发生:

脏读:一个事务读到了另一个事务未提交的数据!!!

1.开启两个窗口A、B!分别连接到MYSQL数据库!

* 分别在两个窗口中查看隔离级别!

* select @@tx_isolation;

2.设置A窗口的隔离级别为read uncommitted

* set session transaction isolation level read uncommitted;

* 查看A窗口的隔离级别

* A:READ-UNCOMMITTED

* B:REPEATABLE-READ

3.两个窗口分别开启事务:

* start transaction;

4.在B窗口中完成转账的代码:但是事务不要提交!

* update account set money = money - 1000 where name = '冠希';

* update account set money = money + 1000 where name = '美美';

5.在A窗口中进行查询:

* select * from account;

* 发现钱已经到账了!!!脏读.(A窗口已经读到B窗口还没有提交的数据)

演示不可重复读的发生(避免脏读)

不可重复读:一个事务读到另一个事务已经提交的数据!(另一个事务update)导致当前的事务多次的查询结果不一致

* 避免脏读:设置隔离级别为read committed

1.开启两个窗口A、B!分别连接到MYSQL数据库!

* 分别在两个窗口中查看隔离级别!

* select @@tx_isolation;

2.在A窗口中设置数据库隔离级别为read committed

* set session transaction isolation level read committed;

* A:READ-COMMITTED

* B:REPEATABLE-READ

3.两个窗口分别开启事务:

* start transaction;

4.在B窗口完成转账代码:

* update account set money = money - 1000 where name = '冠希';

* update account set money = money + 1000 where name = '美美';

***** 先不提交事务!

5.在A窗口进行查询!

* select * from account;

* 这个时候钱没有到账!(避免脏读了 一个事务没有读到另一个事务未提交的数据)

6.在B窗口提交事务:

* commit;

7.在A窗口再次去查询!

* select * from account;

* 发现这次结果和上次的结果不一致(两次查询是在一个事务中的!):不可重复读.

演示避免不可重复读

1.开启两个窗口A、B!分别连接到MYSQL数据库!

* 分别在两个窗口中查看隔离级别!

* select @@tx_isolation;

2.设置A窗口的隔离级别:repeatable read

* set session transaction isolation level repeatable read;

* A:REPEATABLE-READ

* B:REPEATABLE-READ

3.两个窗口分别开启事务:

* start transaction;

4.在B窗口完成转账:

* update account set money = money - 1000 where name = '冠希';

* update account set money = money + 1000 where name = '美美';

事务没有提交

5.在A窗口查询:

* select * from account;

* 数据没有变化:避免脏读!

6.在B窗口提交事务:

* commit;

7.在A窗口再次查询:

* select * from account;

* 数据还是没有变化:避免了不可重复读!

演示隔离级别为serializable:

Serializable:串行的!可以避免脏读、不可重复读、虚读!

1.开启两个窗口A、B!分别连接到MYSQL数据库!

* 分别在两个窗口中查看隔离级别!

* select @@tx_isolation;

2.设置A窗口的隔离级别为 Serializable

* set session transaction isolation level Serializable;

* A:SERIALIZABLE

* B:REPEATABLE-READ

3.在两个窗口分别开启事务:

* start transaction;

4.在B窗口中插入一条记录:

* 事务不提交:

5.在A窗口中进行查询:

* select * from account;

* 屏幕卡住了:因为另一个事务没有提交.这个事务就不能执行,串行的!!!

1.1.5 JDBC中如何设置隔离级别

通过Connection对象的:

* setTransactionIsolation(int level) ;

Connection中有以下的常量:

static int TRANSACTION_READ_COMMITTED

指示不可以发生脏读的常量;不可重复读和虚读可以发生。

static int TRANSACTION_READ_UNCOMMITTED

指示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量。

static int TRANSACTION_REPEATABLE_READ

指示不可以发生脏读和不可重复读的常量;虚读可以发生。

static int TRANSACTION_SERIALIZABLE

指示不可以发生脏读、不可重复读和虚读的常量。

1.1.6 丢失更新:(扩展)

第一类丢失更新

A事务撤销时,把已提交的B事务的数据覆盖掉。这种错误会造成非常严重的后果。

第二类丢失更新

A事务提交时,把已提交的B事务的数据覆盖掉。这种错误会造成非常严重的后果。

解决丢失更新问题:

* 悲观锁:假设丢失更新一定存在!

* 使用的是数据库的一种锁机制:排他锁.

* 乐观锁:假设丢失更新不一定存在!

1.2 连接池

1.2.1 什么是连接池

连接池:就是一个装了很多连接一个容器.(内存中的一块空间,装了很多连接.)

1.2.2 使用连接池:

1.编写一个类 实现DataSource接口.

2.重写getConnection()的方法.

自定义连接池的代码:

public class MyDataSource implements DataSource{

private List<Connection> list = new ArrayList<Connection>();

// 提供一个构造方法:

public MyDataSource(){

// 创建3个连接

for (int i = 1; i <=3; i++) {

// 向list集合放入连接

list.add(JDBCUtils.getConnection());

}

}

// 从连接池中获得连接

public Connection getConnection() throws SQLException {

// 从连接池中获得连接.连接池的扩容

if(list.isEmpty()){

for (int i = 1; i <=3; i++) {

// 向list集合放入连接

list.add(JDBCUtils.getConnection());

}

}

Connection conn = list.remove(0);

return conn;

}

// 用完之后,不是销毁连接而是归还到连接池

public void addBack(Connection conn){

list.add(conn);

}

public PrintWriter getLogWriter() throws SQLException {

return null;

}

public void setLogWriter(PrintWriter out) throws SQLException {

}

public void setLoginTimeout(int seconds) throws SQLException {

}

public int getLoginTimeout() throws SQLException {

return 0;

}

public <T> T unwrap(Class<T> iface) throws SQLException {

return null;

}

public boolean isWrapperFor(Class<?> iface) throws SQLException {

return false;

}

public Connection getConnection(String username, String password)

throws SQLException {

return null;

}

}

****** 自定义连接池中在使用的使用!需要让程序员额外记住一些自定义的方法例如addBack();而且在构造的时候不能使用接口构造.

能不能有一种方式实现:使用接口构造连接池,而且在归还的时候不需要额外提供方法???

* 原来的Connection的close方法是将连接对象销毁!现在是否可以增强close方法,使方法的逻辑改变,归还连接而不是销毁连接?

* 增强Java中类的方法有几种方式?

* 继承 :

class Person{

public void run(){

System.out.println("跑步1000米...");

}

}

class SuperPerson extends Person{

@Override

public void run() {

// super.run();

System.out.println("跑步10000米...");

}

}

测试:

@Test

public void demo1(){

Person p = new SuperPerson();

p.run(); // 子类的方法.

}

***** 继承这种增强某个类的方法使用条件的:

* 必须能够控制这个类的构造!

* 装饰者模式 :

代码:

interface Bird{

public void fly();

}

// 被增强的类

class MaQue implements Bird{

public void fly() {

System.out.println("飞200米...");

}

}

// 增强的类

class DaMaQue implements Bird{

private Bird bird;

public DaMaQue(Bird bird){

this.bird = bird;

}

public void fly() {

bird.fly();

System.out.println("飞500米...");

}

}

测试:

@Test

public void demo1(){

// Bird bird = new MaQue();

// bird.fly();

Bird bird = new DaMaQue(new MaQue());// IO流

bird.fly();

}

***** 装饰者这种增强某个类的方法使用条件的:

* 1.增强类和被增强类实现相同的接口.

* 2.在增强的类中获得到被增强类的引用.

***** 缺点:

* 接口中的方法特别多!

* 动态代理 :

1.2.3 DBCP连接池:

DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接池项目,也是 tomcat 使用的连接池组件。

使用DBCP连接池

1.引入jar包:

* commons-dbcp-1.4.jar

* commons-pool-1.5.6.jar

2.核心类:

* BasicDataSource

* 手动设置参数.

* BasicDataSourceFactory

* 采用配置文件的方式.

1.2.4 C3P0连接池:

C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等

使用C3P0连接池

1.导入jar包:

* c3p0-0.9.1.2.jar

2.ComboPooledDataSource

1.2.5 Tomcat内置连接池:(JNDI技术.)

JNDI:Java Naming and Directory Interface,Java命名和目录接口.

* 对一个Java对象起一个名字.通过这个名称查找到该对象.

JNDI连接池:

* 需要有一个配置:<Context>标签的配置.

* <Context>标签:在Tomcat学习的时候使用.配置Tomcat的虚拟路径.

* <Context>标签可以配置在三个地方:

* Tomcat/conf/context.xml:可以被Tomcat下的所有的虚拟主机、虚拟路径访问!

* Tomcat/conf/Catalina/localhost/context.xml:可以Tomcat下的localhost虚拟主机下的所有路径访问!

* 当前的工程下/META-INF/context.xml:只能被当前的工程访问!

使用JNDI连接池:

* 1.在工程的/META-INF/创建一个context.xml

<Context>

<Resource name="jdbc/EmployeeDB" auth="Container"

type="javax.sql.DataSource" username="root" password="123"

driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql:///day18"

maxActive="8" maxIdle="4"/>

</Context>

* 2.Tomcat维护这些连接.这些连接是由Tomcat服务器创建的.

* 必须在Tomcat/lib下copy一个数据库驱动包.

* 3.操作连接池这个类必须是运行在Tomcat服务器中的类!

* 运行在Tomcat中的类是Servlet!!!

jdbc事务处理和连接池的更多相关文章

  1. eclipse下jdbc数据源与连接池的配置及功能简介

    今天在做四则运算网页版的时候遇到了一个困惑,由于需要把每个产生的式子存进 数据库,所以就需要很多次重复的加载驱动,建立连接等操作,这样一方面写程序不方便,加大了程序量,另一方面,还有导致数据库的性能急 ...

  2. jdbc基础 (五) 连接池与数据源 DBCP以及C3P0的使用

    一.连接池的概念和使用 在实际应用开发中,特别是在WEB应用系统中,如果JSP.Servlet或EJB使用JDBC直接访问数据库中的数据,每一次数据访问请求都必须经历建立数据库连接.打开数据库.存取数 ...

  3. JDBC第一天连接池案例

    JDBC,JDBC的工具类JDBC 连接从连接池中拿: 创建连接池的语句: package day01; import java.sql.Connection; import java.sql.Dri ...

  4. JDBC创建mysql连接池代码

    1.底层实现类(DBConnection) package JDBC.JDBCPool.MyJDBCPool; import java.sql.Connection; import java.sql. ...

  5. 【JDBC】C3P0连接池的使用

    C3P0连接池的c3p0-config.xml配置文件 <?xml version="1.0" encoding="UTF-8"?> <c3p ...

  6. Spring整合JDBC和Druid连接池

    我的博客名为黑客之谜,喜欢我的,或者喜欢未来的大神,点一波关注吧!顺便说一下,双十二快到了,祝大家双十二快乐,尽情的买买买~ 如果转载我的文章请标明出处和著名,谢谢配合. 我的博客地址为: https ...

  7. jdbc事务、连接池概念、c3p0、Driud、JDBC Template、DBUtils

    JDBC 事务控制 什么是事务:一个包含多个步骤或者业务操作.如果这个业务或者多个步骤被事务管理,则这多个步骤要么同时成功,要么回滚(多个步骤同时执行失败),这多个步骤是一个整体,不可分割的. 操作: ...

  8. jdbc pool java连接池技术

    1 ConnectPool .java: 2 3 package pool; 4 5 /** 6 * Title: ConnectPool.Java 7 * Description: 连接池治理器 8 ...

  9. 常用的jdbc的Druid连接池配置

    spring: datasource: username: root password: 888888 url: jdbc:mysql://localhost:3306/mybatis driver- ...

随机推荐

  1. OC-ARC

    一. 基本简介 ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain.release.autorelease语句.你不再需要担心内存管理, ...

  2. OC-成员变量的作用域

    #import <Foundation/Foundation.h> @interface Person : NSObject { int _no; @public // 在任何地方都能直接 ...

  3. MV*模式的个人理解

    MV*模式主要解决的问题就是 View代码难以维护的问题. MV*模式将View中的逻辑分离出去,形成一个弱逻辑的易于维护的视图. MV*中的*是Model和View的桥梁,负责保持Model和Vie ...

  4. YII2数据库依赖缓存

    首先配置一下缓存,自己选择是用文件缓存还是数据库缓存等. 'cache' => [ 'class' => 'yii\caching\FileCache', ], 然后就可以通过 Yii:: ...

  5. C# 协变out 、逆变 in

    需求:泛型使用多态性 备注:协变逆变只能修饰 接口和委托 简单理解: 1.使用 in 修饰后为逆变,只能用作形参使用 ,参考 public delegate void Action<in T&g ...

  6. 『MySQL』索引类型 normal, unique, full text

    问题1:mysql索引类型normal,unique,full text的区别是什么? normal:表示普通索引 unique:表示唯一的,不允许重复的索引,如果该字段信息保证不会重复例如身份证号用 ...

  7. motto2

    Baby you've done enough that cut your breath.Don't beat yourself up don't need to turn so fast.Somet ...

  8. python4delphi 使用

    Python 开发桌面程序, 之前写过一个使用IronPython的博客. 下面这个方案使用 delphi 作为主开发语言,通过 python4delphi 控件包将 python 作为 script ...

  9. 由json字符串生成C#实体类的工具

    json作为互联网上轻量便捷的数据传输格式,越来越受到重视.但在服务器端编程过程中,我们常常希望能通过智能提示来提高编码效率.JSON C# Class Generator 能将json格式所表示的J ...

  10. 《深入浅出WPF》笔记四

    1.WPF资源分布:数据库.资源文件.WPF对象资源.变量2.每个WPF的界面都具有一个名为Resources的属性,其类型为ResourceDictionary,以键值对的形式存储资源.3.检索资源 ...