一、事务

事务是指一个工作单元,它包括了一组加入,删除,改动等数据操作命令,这组命令作为一个总体向系统提交运行,要么都运行成功,要么所有恢复

在JDBC中使用事务

1)con.setAutoCommit(false),取消自己主动提交

2)对数据库运行一个或多个操作(一个或多个SQL语句)

3)con.commit()。提交事务(上面的第二部的多个操作就作为一个总体提交运行)

4)假设某个操作失败。通过con.rollback()回滚全部操作(撤销以上的操作,将数据恢复为运行前状态)

事务处理依赖于底层的数据库实现,不同的驱动程序对事务处理的支持程度可能不同

语法

Connection con = DriverManger.getConnection(urlString);

con.setAutoCommit(false);

Statement stm = con.createStatement();

stm.executeUpdate(sqlString);

con.transactionEndMethod; //con.commit() or con.rollback();

演示样例:

try{ con.setAutoCommit(false);

    stm = con.createStatement();

    stm.executeUpdate(

       “insert into t_user(id, name, password) values(1, ‘admin’,’admin’ )”);

    con.commit(); ……数据操作代码……con.commit();}

 catch(SQLException e) {

        try {con.rollback();} catch(Exception e){}

 }

二、数据库并发

数据库并发就是不同的事务对同一部分数据运行操作

事务T1和T2(或多个事务)对同一部分数据进行改,删,查操作:T1  进行改动而T2进行查询。

数据库并发easy导致的问题

1)读脏数据:事务T1改动某一数据。并将其写回数据库,事务T2读取同一数据后。T1因为某种原因被撤消。这时T1已改动过的数据恢复原值。T2读到的数据就与数据库中的数据不一致,我们称T2读到的数据就为"脏"数据,即不对的数据。

2)不可反复读:不可反复读是指事务T1读取数据后,事务T2运行更新操作,使T1无法再现前一次读取结果。

3)幻读:事务T1按一定条件从数据库中读取某些数据记录后,事务T2插入了一些记录,当T1再次按同样条件读取数据时,发现多了一些记录。

并发控制

1)数据库并发控制就是要用正确的方式调度并发操作,使一个用户事务的运行不受其他事务的干扰,从而避免造成数据的不一致

在JDBC中。通过connection能够设置事务隔离级别来对并发进行控制

2)事务隔离级别就是事务运行时受打搅的程度,不同隔离级别相应不同的干扰程度,隔离级别越高。数据一致性就越好,但并发性越差。效率越低。

Connection中查看和设置隔离级别的方法

getTransactionIsolation():查看隔离级别

setTransactionIsolation(int  level):设置隔离级别

Connection中的事务隔离级别(Connection接口中的常量)

TRANSACTION_NONE:此级别不支持事务

TRANSACTION_READ_UNCOMMITTED:此级别同意某一事务读其它事务还没有更改完的数据。

同意发生脏读 、不可反复读和幻读。

TRANSACTION_READ_COMMITTED:此级别要求某一事务仅仅能等别的事务所有更改完才干读。

能够防止发生脏读,但不可反复读和幻读有可能发生。

TRANSACTION_REPEATABLE_READ:此级别要求某一事务仅仅能等别的事务所有更改完才干读并且禁止不可反复读。

也就是能够防止脏读和不可反复读,但幻读有可能发生。

TRANSACTION_SERIALIZABLE:此级别防止发生脏读、不可反复读和幻读,事务仅仅能一个接着一个地运行。而不能并发运行。

3)语法

con.setTransactionIsolation(Connection.isolationLevel);

演示样例:

Connection con = DriverManager.getConnection

(“jdbc:mysql://localhost:3306/test”, “root”, “root”);

con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

三、行集

1)行集是从表格式数据源中检索出来的一行或多行数据:

与结果集(ResultSet)类似(RowSet接口继承了ResultSet接口)

可是使用结果集时与数据库的连接不能断开。而行集是能够在关闭连接的情况下存在的,行集一般在关闭连接的情况下使用。仅仅有在进行一些特殊操作

时须要才建立连接

2)行集中的数据来源:

使用JDBC驱动程序从数据库检索的数据

从其它数据源获得的数据,如文件数据

行集(Row  Set)的长处:

1)能够断开数据库连接操作数据

2)能够在分布式系统中的不同组件之间传递

3)默认可更新,可滚动,可序列化,能够方便的在网络间传输

4)能够方便的使数据在行集与JavaBean对象之间进行转换

行集中的一行数据能够封装为一个JavaBean对象

JavaBean是一个类。类中有若干私有属性,然后有与属性相关的公有的get和set方法。这样,我们能够将一行数据存入一个JavaBean对象中

行集相关接口:

javax.sql.RowSet:全部行集的父接口

java.sql.rowset.CachedRowSet:数据行容器,能够在内存中缓存各行数据。在对数据进行操作时不须要连接到数据源。能够改动CachedRowSet对象中的数据,这些改动随后能够被更新到数据库。

同一时候,也是一个JavaBean组件。可滚动,可更新,可序列化。

java.sql.rowset.JDBCRowSet:数据行容器。可滚动,可更新。

始终连接到数据库。

java.sql.rowset.WebRowSet:被缓存的行集,该行集数据能够保存为xml文件。

java.sql.rowset.JoinRowSet:数据行容器,这些数据取自那些形成SQL JOIN关系的RowSet对象。有连接和无连接的RowSet对象都可成为JOIN的一部分。

java.sql.rowset.FilteredRowSet:数据行容器,能够对数据进行条件过滤。

行集的填充:

1)传统JDBC方式

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

String  connectionUrl = 

“jdbc:mysql://localhost:3306/test?user=root&password=root "; 

Connection  connection = DriverManager.getConnection(connectionUrl);

Statement  statement = connection.createStatement();

ResultSet  rs = statement.executeQuery(sql);

CachedRowSetImpl  rowset = new CachedRowSetImpl();

rowset.populate(rs); 

rs.close(); statement.close();connection.close();

2)设置行集属性连接数据库并检索数据

CachedRowSetImpl  rowset = new CachedRowSetImpl();

rowset.setUrl(“jdbc:mysql://127.0.0.1:3306/test”);

rowset.setUsername(“root”);

rowset.setPassword(“test”);

rowset.setCommand(“select  *  from  student”);

rowset.execute();

其它的填充方式:

XML

Excel

……

-------------------------------------------------------------------------------------------------------------------------------

RowSet的使用:

1、下面行集类使用Java的默认实现类

CachedRowSetImpl rowset = new CachedRowSetImpl();  

//CachedRowSetImpl是SUN定义的CachedRow接口默认实现类

Statement statement = connection.createStatement();

ResultSet  rs = statement.executeQuery(“select  *  from  table1”);

rowset.populate(rs);        //填充行集

rs.close(); statement.close();connection.close();    //关闭连接

//显示CachedRow数据。使用从结果集继承的方法

while (rowset.next()) {   

System.out.print(rowset.getString(1) + " : ");   
System.out.println(rowset.getString("CompanyName"));   

}

2、//更新CachedRow数据(conn.setAutoCommit(false);)

crs.last();

crs.updateShort(3, 58);

crs.updateInt(4, 150000);

crs.updateRow();                             //更新行集

crs.acceptChanges(conn);      //更新数据库 

注意事项:

使用行集改动数据与行集中的数据填充方式无关。可是要保证acceptChanges()方法运行时有可用的连接对象,假设行集中有可用的连接对象能够调用acceptChanges()。假设行集中没有可用的连接对象,须要调用acceptChanges(Connection)方法。

使用行集对数据进行加入、改动、删除时,必须保证事务提交为非自己主动提交(acceptChanges()方法会调用commit()方法)。

3、//加入数据

crs.setTableName(“student”);     //加入数据必须指定

crs.moveToInsertRow();                   //标识指针的位置

crs.updateInt(“id”,33);            //加入数据时主键必须指定

crs.updateString(“name", "Shakespeare");

crs.updateShort(“age", 58);

crs.insertRow();                                 //更新行集

crs.moveToCurrentRow();            //让指针回到标识的位置

crs.acceptChanges(conn);                 //更新数据库



//删除数据

crs.first();

crs.deleteRow();                               //删除行集数据

crs.acceptChanges(conn);              //更新数据库

4、//分页1:使用结果集填充行集

rs = stm.executeQuery(“select  *  from  student”);

crs.setPageSize(4);          //设置每页行数

crs.populate(rs, 10);        //从结果集的第十行開始取4行数据填充行集



crs.nextPage();                //获得兴许页数据,假设有数据返回true





注意:

此时resultset,statement(preparedstatement),connection不能关闭。否则行集无法取得兴许页数据

5、//分页2:行集建立连接从数据库读取数据

CachedRowSetImpl  crs= new CachedRowSetImpl();

crs.setUrl(“jdbc:mysql://127.0.0.1:3306/test”);

crs.setUsername(“root”);

crs.setPassword(“root”);

crs.setCommand(“select  *  from  student”);

crs.setPageSize(4);       //每页行数。一定要在execute()方法运行前设置。否则无效

crs.execute();

……

crs.nextPage();          //获得下一页的数据。与结果集,连接对象无关

……

下面是相关測试代码:

package com;

import java.sql.SQLException;

import com.sun.rowset.CachedRowSetImpl;

public class JDBC4 {
public static void main(String[] args) {
try {
CachedRowSetImpl rowset=new CachedRowSetImpl();
rowset.setUrl("jdbc:mysql://localhost:3308/test");
rowset.setUsername("root");
rowset.setPassword("123456");
rowset.setCommand("select*from score;");
rowset.execute();
//输出行集数据
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
package com;

import java.sql.SQLException;

import com.sun.rowset.CachedRowSetImpl;

public class JDBC6 {
public static void main(String[] args) {
try {
CachedRowSetImpl rowset=new CachedRowSetImpl();
rowset.setUrl("jdbc:mysql://localhost:3308/test");
rowset.setUsername("root");
rowset.setPassword("123456");
rowset.setCommand("select*from score;");
//设置每页显示的数据条数
rowset.setPageSize(3);
rowset.execute();
int i=2;
System.out.println("第1页");
System.out.println("id\tChinese\tEnglish\thistory"); while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
while(rowset.nextPage()){
System.out.println("第"+i+"页");
i++;
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
}
} catch (SQLException e) {
e.printStackTrace();
} }
}
package com;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import com.sun.rowset.CachedRowSetImpl; import util.DBUtil; public class JDBC3 {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement pst=null;
ResultSet rs=null;
DBUtil util=new DBUtil();
String sql="select*from score";
try {
conn=util.getConn();
pst=conn.prepareStatement(sql);
//必须设置非自己主动提交
conn.setAutoCommit(false);
rs=pst.executeQuery();
//创建行集实例
CachedRowSetImpl rowset=new CachedRowSetImpl();
//填充
rowset.populate(rs);
rs.close();
pst.close();
rowset.absolute(5);
//rowset.updateInt("id", 5);
rowset.updateInt("English", 55);
//更新
rowset.updateRow();
//提交
rowset.acceptChanges(conn); //输出结果集之前,关闭连接
conn.close(); //输出行集数据
System.out.println("id\tChinese\tEnglish\thistory");
while(rowset.next()){
System.out.print(rowset.getInt("id")+"\t");
System.out.print(rowset.getInt("Chinese")+"\t");
System.out.print(rowset.getInt("English")+"\t");
System.out.println(rowset.getInt("history"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

JDBC高级特性(二)事务、并发控制和行集的更多相关文章

  1. 深入浅出Redis(二)高级特性:事务

    第一篇中介绍了Redis是一个强大的键-值仓储,支持五种灵活的数据结构.其实,Redis还支持其他的一些高级特性:事务.公布与订阅.管道.脚本等,本篇我们来看一下事务. 前一篇中我们提到,在Redis ...

  2. JDBC高级特性(一)结果集,批量更新

    一.ResultSet的高级特性 1 可滚动ResultSet 1)向前和向后滚动 滚动特性 在JDBC初期版本号中, ResultSet仅能向前滚动 在JDBC兴许版本号中, ResultSet默认 ...

  3. Java JDBC高级特性

    1.JDBC批处理 实际开发中需要向数据库发送多条SQL语句,这时,如果逐条执行SQL语句,效率会很低,因此可以使用JDBC提供的批处理机制.Statement和PreparedStatemen都实现 ...

  4. PHP高级特性二之文件处理

    PHP中的文件处理也是一个相当重要的模块,这一篇的主要内容就是PHP中文件系统的简介. 文件系统用途 1. 项目处理都离不开文件处理 2. 可以用文件长时间保存数据 3. 建立缓存,在服务器中进行文件 ...

  5. JVM高级特性-二、JVM在堆中对象的分配、布局、访问过程

    前面介绍了jvm运行时数据区域后,下面讲解下对内存中数据的其他细节,看他们是如何创建.布局及访问的 一.对象的创建 1.对象的分配 对象的创建分配方式主要有两种:指针碰撞和空闲列表 指针碰撞: 假设堆 ...

  6. logback高级特性二 异步记录日志

    问题描述: 下图中JProfiler可看出logback的日志输出占了64%的cpu消耗 优化方案: 1. 这部分写日志的代码写了一些报文数据,确实是比较大的字符串.先禁掉控制台输出,生产环境也不需要 ...

  7. Java数据库连接--JDBC调用存储过程,事务管理和高级应用

    相关链接:Jdbc调用存储过程 一.JDBC常用的API深入详解及存储过程的调用 1.存储过程的介绍 我们常用的操作数据库语言SQL语句在执行的时候要先进行编译,然后执行,而存储过程是在大型数据库系统 ...

  8. (十二)boost库之多线程高级特性

    (十二)boost库之多线程高级特性 很多时候,线程不仅仅是执行一些耗时操作,可能我们还需要得到线程的返回值,一般的处理方法就是定义一个全局状态变量,不断轮训状态,就如我目前维护的一个项目,全局变量定 ...

  9. 【Redis】二、Redis高级特性

    (三) Redis高级特性   前面我们介绍了Redis的五种基本的数据类型,灵活运用这五种数据类型是使用Redis的基础,除此之外,Redis还有一些特性,掌握这些特性能对Redis有进一步的了解, ...

随机推荐

  1. python学习二,字符串常用操作

    字符串可以说是在日常开发中应用最广泛的了,现在来总结下有关python中有关字符串一些常用操作 首先我们声明一个字符串变量 str = "hello world" 下面我们来依次介 ...

  2. mysql中group by和order by混用 结果不是理想结果

    在使用mysql排序的时候会想到按照降序分组来获得一组数据,而使用order by往往得到的不是理想中的结果,那么怎么才能使用group by 和order by得到理想中的数据结果呢? 例如 有一个 ...

  3. Git学习总结(5)——搭建Git简易高效服务器

    1. mysysgit+gitblit安装流程 1.1资源  需先下载好的资源(公司用的1.6,1.7+请自行匹配对应的mysysgit+gitblit):  jdk1.6  Git-1.8.4-pr ...

  4. java.lang.IllegalArgumentException: The observer is null.终于解决方式

    java.lang.IllegalArgumentException: The observer is null.终于解决方式 在使用数据适配的时候的问题: java.lang.IllegalArgu ...

  5. 认识 Atlassian Datacenter 产品

    认识 Atlassian Datacenter 产品 云端原本就是群集化的架构,Atlassian 系列产品.应用的开发团队相当广范且行之有年,可是将应用程序作为节点(比方Jira,confluenc ...

  6. 在jsp页面中导入BootStrap中的文件

    BootStrap应该放在项目的根目录下面 然后因为我的jsp页面跟html页面是写在HTML文件夹中,所以我路径的导入应该像下面的图一样,退回到上级目录再写路径.

  7. 动态规划 LCS,LIS

    1.最大连续子序列 dp[i]=max(dp[i-1]+a[i],a[i]) 以i为结尾 2.最大不连续子序列 dp[i]=max(dp[j]+a[i],dp[j]) 3.最大连续递增子序列 if a ...

  8. 深入浅出微服务框架dubbo(一):基础篇

    一.基础篇 1.1 开篇说明 dubbo是一个分布式服务框架,致力于提供高性能透明化RPC远程调用方案,提供SOA服务治理解决方案.本文旨在将对dubbo的使用和学习总结起来,深入源码探究原理,以备今 ...

  9. Android 将HTML5封装成android应用APK文件的几种方法

    越来越多的开发者热衷于使用html5+JavaScript开发移动Web App.不过,HTML5 Web APP的出现能否在未来取代移动应用,就目前来说,还是个未知数.一方面,用户在使用习惯上,不喜 ...

  10. PHP截取字符串长度

    <?php function str_cut($string, $start=0,$length, $dot = '..') {    $strlen = strlen($string);    ...