1.数据库简介
数据库(DB,Data Base )
数据库管理系统(DBMS,Data Base Management System)
关系型数据库(RDB)
关系型数据库管理系统(RDBMS)
SQL语言(Structured Query Language):使用关系模型的数据库语言,用于和各类数据库的交互,提供通用的数据管理和查询功能。
常用SQL指令:(CURD)
SELECT 、INSERT、DELETE、UPDATE、CREATE、DROP
ODBC(Open DataBase Connectivity,开放式数据库互连):数据库系统应用程序接口规范。
支持应用程序以标准的ODBC函数和SQL语句操作各种不同类型的数据库。
2.JDBC(Java DataBase Connectivity)
JDBC功能:
①支持基本SQL语句,在Java程序中实现数据库操作功能并简化操作过程
②提供多样化的数据库连接方法
③为各种不同的数据库提供统一的操作界面
JDBC API:
java.sql. DriverManager类:驱动管理类
java.sql.Driver接口
java.sql.Connection接口:与特定的数据库之间的连接
java.sql.Statement接口:指定数据库连接和要执行的sql表达式就可以执行sql语句
java.sql.ResultSet接口:返回结果
原理:首先要将不同的数据库驱动程序加载到驱动程序管理器
3.JDBC驱动程序
数据库驱动程序(DataBase Driver)
JDBC驱动程序分类:
第一类:JDBC-OCBC桥(并不常用)
第二类:Java到本地API(本地API是指本机安装了目标数据库的客户端,但是不通用,因为必须要安装客户端)
第三类:Java到网络协议(通过网络协议实现数据库操作,服务器端需要有特定的协议)
第四类:Java到数据库协议(速度最快,但是不具备通用性,必须要为各种数据库配置相应的协议)
4.数据库URL
JDBC技术中使用数据库URL来标识目标数据库 数据库URL格式:jdbc:<子协议名>:<子名称>
"jdbc"为协议名,确定不变;
<子协议名>指定目标数据库的种类和具体连接方式;
<子名称>指定具体的数据库/数据源连接信息(如数据库服务器的IP地址/通信端口号、ODBC数据源名称、连接用户名/密码等)。
子名称的格式和内容随子协议的不同而改变。
举例:
jdbc:oracle:thin:@166.111.78.98:1521:ora9
jdbc:microsoft:sqlserver://127.0.0.1:1433
jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=pubs
关于oracle的thin和oci的方式访问的区别请见:http://www.cnblogs.com/phoebus0501/archive/2011/05/12/2044725.html
5.JDBC编程基本步骤
1. 加载 驱 动 程 序 ( 向 系 统 注 册 所 需 的 JDBC 驱 动 程序);
2. 建立到指定数据库的连接;
3. 提交数据库查询;
4. 取得查询结果
MySQL 数据库的一个简单实例:
package v512.chap18;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JDBCExample {
public static void main(String[] args) {
try {
Class.forName("org.gjt.mm.mysql.Driver");
String url ="jdbc:mysql://localhost/blog";
Connection connection = DriverManager.getConnection(url,"root","yinger");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select id,title from blog");
while (resultSet.next()) {
System.err.println(resultSet.getInt("id")+":"+resultSet.getString("title"));
}
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1. MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar
Class.forName( "org.gjt.mm.mysql.Driver" );
cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );
2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar
Class.forName( "org.postgresql.Driver" );
cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );
3. Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip
Class.forName( "oracle.jdbc.driver.OracleDriver" );
cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );
例如:
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:orcale";
conn = DriverManager.getConnection(url,"scott","tiger");
4. Sybase(http://jtds.sourceforge.net)jconn2.jar
Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" );
cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );
// (Default-Username/Password: "dba"/"sql")
5. Microsoft SQLServer(http://jtds.sourceforge.net)
Class.forName( "net.sourceforge.jtds.jdbc.Driver" );
cn = DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );
6. Microsoft SQLServer(http://www.microsoft.com)
Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );
cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master", sUsr, sPwd );
7. ODBC
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );
8.DB2
Class.forName("Com.ibm.db2.jdbc.net.DB2Driver");
String url="jdbc:db2://192.9.200.108:6789/SAMPLE"
cn = DriverManager.getConnection( url, sUsr, sPwd );
6.左图是 ResultSet的getXXX()方法,右图是SQL和Java的类型对应关系
7.获取数据库元数据
数据库元数据:数据库的相关信息
实例:
package v512.chap18;
import java.sql.*;
public class TestMetaData{
public static void main(String args[]){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:orcale";
conn = DriverManager.getConnection(url,"scott","tiger");
ResultSet rs = null;
DatabaseMetaData dmd = conn.getMetaData();
if (dmd == null) {
System.out.println ("No Meta available");
} else {
System.out.println ("数据库名称:" + dmd.getDatabaseProductName());
System.out.println ("数据库版本:" + dmd.getDatabaseProductVersion());
System.out.println ("数据库驱动程序:" + dmd.getDriverName());
System.out.println ("驱动程序版本号:" + dmd.getDriverVersion());
System.out.println ("并发访问的用户个数" + dmd.getMaxConnections());
System.out.println ("数据类型列表:" );
rs = dmd.getTypeInfo();
while(rs.next()){
System.out.println("\t" + rs.getString(1));
}
rs.close();
}
Statement stmt = conn.createStatement();
String s = "select * from dept";
rs = stmt.executeQuery(s);
System.out.println("数据表dept结构信息:");
ResultSetMetaData rsm = rs.getMetaData();
int columnCount = rsm.getColumnCount();
System.out.println("列序号\t列名\t数据类型");
for(int i=1;i<=columnCount;i++){
System.out.println(" " + i + " \t" +
rsm.getColumnName(i) + "\t" +
rsm.getColumnTypeName(i));
}
rs.close();
stmt.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null && !conn.isClosed()){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
返回的结果:
数据库名称:Oracle
数据库版本:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
数据库驱动程序:Oracle JDBC driver
驱动程序版本号:11.2.0.1.0
并发访问的用户个数0
数据类型列表:
INTERVALDS
INTERVALYM
TIMESTAMP WITH LOCAL TIME ZONE
TIMESTAMP WITH TIME ZONE
NUMBER
NUMBER
NUMBER
LONG RAW
RAW
LONG
CHAR
NUMBER
NUMBER
NUMBER
FLOAT
REAL
VARCHAR2
DATE
DATE
TIMESTAMP
STRUCT
ARRAY
BLOB
CLOB
REF
数据表dept结构信息:
列序号 列名 数据类型
1 DEPTNO NUMBER
2 DNAME VARCHAR2
3 LOC VARCHAR2
8.访问SQL Server数据库
准备SQL Server数据库JDBC驱动程序
1. 从微软网站下载JDBC驱动程序安装文件
2. 本地安装该驱动程序包
3. 重新设置CLASSPATH环境变量
9.JDBC-ODBC编程
工作原理:
JDBC驱动程序管理器并不直接操纵数据库驱动程序,而是调用JDBC-ODBC 桥驱动程序操纵ODBC 驱动程序,进而连接各种类型的数据库。
JDBC驱动程序 -> JDBC-ODBC 桥驱动程序 -> ODBC 驱动程序 -> 各种类型的数据库 [可以结合上面的几幅图来理解]
可以封装很多的数据库或者数据文件:excel,access,SQL Server。。。
编程步骤:
第一步:创建ODBC数据源 (在Windows操作系统中把目标数据库封装成ODBC数据源)
找到 ODBC
配置好一个 ODBC 数据源
第二步:在程序中连接并操作ODBC数据源
package v512.chap18;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class ODBCExample {
public static void main(String[] args) {
try {
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
Connection connection = DriverManager.getConnection("jdbc:odbc:MyExcelODBC1");
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from [Sheet1$]");
while (resultSet.next()) {//注意,索引是从1开始的,否则报错:[Microsoft][ODBC 驱动程序管理器] 无效的描述器索引
System.out.println("name:"+resultSet.getString(1)+"---tel:"+resultSet.getString(2));
}
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Excel文件中的内容:
程序运行输出结果:
name:yinger---tel:15079576419.0
name:胡吉清---tel:13707950937.0
name:刘明---tel:13842879813.0
name:小熊强---tel:15244672815.0
name:朱思瑞---tel:13920137236.0
name:马继鸣---tel:13548607626.0
name:魏纪元---tel:13739068492.0
name:王晨龙---tel:13807493710.0
name:王沛东---tel:13875803565.0
name:杨阳---tel:13875810771.0
name:邹星乾---tel:13875960663.0
name:刘龙---tel:13875831389.0
name:易兵---tel:13875995083.0
name:张华敏---tel:13875972761.0
name:杨颖华---tel:13875953921.0
name:张丹羊---tel:15873116080.0
name:大哥---tel:13720254940.0
除了末尾多了个.0之外其他的数据都是没有问题的!
10.使用属性文件配置环境
将数据库连接信息(URL、用户名/密码等)保存到专门的属性文件中,而不在程序中直接给出
属性文件:
#Mysql db info
db_url = jdbc:mysql://localhost/blog
username = root
password = root
测试类:
package v512.chap18;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
public class JDBCExample {
public static void main(String[] args) {
try {
Class.forName("org.gjt.mm.mysql.Driver");
// //直接编写得到连接
String url ="jdbc:mysql://localhost/blog";
// Connection connection = DriverManager.getConnection(url,"root","root");
//读取配置文件得到连接
Properties properties = new Properties();
FileInputStream fileInputStream = new FileInputStream("E:\\mydb.properties");
properties.load(fileInputStream);
// String url = properties.getProperty("db_url");
System.out.println(url);
String username = properties.getProperty("username");
System.out.println(username);
String password = properties.getProperty("password");
System.out.println(password);
Connection connection = DriverManager.getConnection(url,username,password);
//进行数据查询
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select id,title from blog");
while (resultSet.next()) {
System.out.println(resultSet.getInt("id")+":"+resultSet.getString("title"));
}
resultSet.close();
statement.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
输出结果:
jdbc:mysql://localhost/blog
root
root
1:I love Java
10:Java JSP
11:Java Servlet
12:Java Spring
14:cnblog
16:very good
17:500 tomcat
11.OCI方式访问Oracle
什么是OCI(Oracle Call Interface)方式?
OCI方式连接时Oracle客户端配置的三种方式:
1.使用Net Configuration Assistant
2.使用Net Manager图形化工具
3.直接修改数据库配置文件"tnsnames.ora" (我的电脑的路径:D:\app\Administrator\product\11.2.0\dbhome_1\NETWORK\ADMIN\tnsnames.ora)
12.可滚动/可更新结果集
结果集类型
不可滚动(FORWARD_ONLY)
滚动不敏感(SCROLL_INSENSITIVE):可以滚动,但是如果数据库中的数据发生了更改不会反映到结果集中
滚动敏感(SCROLL_SENSITIVE)
结果集的并发模式
只读的(READ_ONLY)
可更新的(UPDATABLE):允许对结果集进行更改,修改或者删除,并且可以将它反应到数据库中
Connection接口中提供的重载方法createStatement()用于获取可滚动/可更新结果集。
方法格式:Statement createStatement(int type, int concurrency)
注意:以上结果集的类型和并发模式受到具体的数据库和数据库驱动程序的限制
可以使用数据库元数据进行测试:
import java.sql.*;
public class TestMetaData{
public static void main(String args[]){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:orcale";
conn = DriverManager.getConnection(url,"scott","tiger");
ResultSet rs = null;
DatabaseMetaData dmd = conn.getMetaData();
if (dmd == null) {
System.out.println ("No Meta available");
} else {
System.out.println ("数据库名称:" + dmd.getDatabaseProductName());
System.out.println ("数据库版本:" + dmd.getDatabaseProductVersion());
System.out.println ("数据库驱动程序:" + dmd.getDriverName());
System.out.println ("驱动程序版本号:" + dmd.getDriverVersion());
System.out.println ("--------------------------------------------");
System.out.println ("结果集类型及支持情况(true-支持,false-不支持)");
System.out.println ("TYPE_FORWARD_ONLY: " +
dmd.supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY));
System.out.println ("TYPE_SCROLL_INSENSITIVE: " +
dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE));
System.out.println ("TYPE_SCROLL_SENSITIVE: " +
dmd.supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE));
System.out.println ("CONCUR_READ_ONLY: " +
dmd.supportsResultSetType(ResultSet.CONCUR_READ_ONLY));
System.out.println ("CONCUR_UPDATABLE: " +
dmd.supportsResultSetType(ResultSet.CONCUR_UPDATABLE));
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
使用可滚动结果集
(1)对于可滚动结果集,可以使用ResultSet 接口中定义的下述方法进行遍历:
boolean next()
boolean previous()
boolean first()
boolean last()
void beforeFirst():第一个的前面,在调用next就是第一个了
void afterLast():最后一个的后面
boolean relative(int rows):相对的移动一定的行数,负数是向前
boolean absolute(int row):绝对移动,移动到某一行
int getRow()
测试方法:
import java.sql.*;
public class TestScrollResultSet{
public static void main(String args[]){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url,"scott","tiger");
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("select * from student");
while(rs.next()){
showOneRow(rs);
}
System.out.println("-----------");
rs.last();
showOneRow(rs);
rs.first();
showOneRow(rs);
rs.beforeFirst();
rs.next();
showOneRow(rs);
rs.absolute(2);
showOneRow(rs);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void showOneRow(ResultSet rs) throws SQLException{
System.out.print("第" + rs.getRow() + "行: ");
System.out.print(rs.getString(1));
System.out.print("\t" + rs.getString(2));
System.out.print("\t" + rs.getString(3));
System.out.println();
}
}
(2)对于可更新结果集,可以使用ResultSet 接口中定义的下述方法进行更新操作:
void updateXXX(String columnName, XXX x)
void updateXXX(int columnIndex, XXX x)
void updateRow():它必须紧跟在上面的方法之后
void moveToInsertRow():在当前的结果集中插入一行,相当于newRow,然后调用updateXXX()和insertRow方法就可以在数据库中插入一行数据
void insertRow()
void moveToCurrentRow():如果当前是在插入一行记录,调用这个方法可以将游标返回到刚才指向的行
void deleteRow()
void cancelRowUpdates()
测试方法:
import java.sql.*;
public class TestUpdatableResultSet{
public static void main(String args[]){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url,"scott","tiger");
Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("select tid,name,salary from teacher");
//ResultSet rs = stmt.executeQuery("select teacher.* from teacher");
//更新前结果集中数据
while(rs.next()){
showOneRow(rs);
}
//更新和删除记录
rs.beforeFirst();
while(rs.next()){
String name = rs.getString("name").trim();
if(name.equals("李四")){
double sal = rs.getDouble("salary");
rs.updateDouble("salary", sal + 8888);
rs.updateRow();
}else if(name.equals("张三")){
rs.deleteRow();
}
}
//插入新记录
rs.moveToInsertRow();
rs.updateInt("tid",1005);
rs.updateString("name","云飞扬");
rs.updateDouble("salary",2840);
rs.insertRow();
rs.close();
//结果集更新后后数据库中数据
System.out.println("--------------------------------------------");
rs = stmt.executeQuery("select * from teacher");
while(rs.next()){
showOneRow(rs);
}
rs.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
public static void showOneRow(ResultSet rs) throws SQLException{
System.out.print("第" + rs.getRow() + "行: ");
System.out.print(rs.getInt(1));
System.out.print("\t" + rs.getString(2));
System.out.print("\t" + rs.getDouble(3));
System.out.println();
}
}
【注意】在实际的开发中并不建议在结果集中进行数据操作然后同步到数据库中
13.预处理语句 PreparedStatement
java.sql.PreparedStatement 接口提供了执行预编译SQL语句的功能,它继承了java.sql.Statement接口。
Connection对象的prepareStatement(String sql)方法可创建并返回PreparedStatement对象。
PreparedStatement接口主要方法:
void setXXX(int parameterIndex, XXX x)
ResultSet executeQuery()
int executeUpdate()
实例:
package v512.chap18;
import java.sql.*;
public class PrepStmt {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pst = null;
try {
Class.forName("org.gjt.mm.mysql.Driver");
String url = "jdbc:mysql://localhost/blog";
con = DriverManager.getConnection(url, "root", "root");
String sql = "insert into blog(categoryid,title,content,created_time) values(?,?,?,?)";
pst = con.prepareStatement(sql);
pst.setInt(1, 1);
pst.setString(2, "Java vs C#");
pst.setString(3, "Java is better than C#");
pst.setDate(4, new Date(2010, 8, 8));
pst.executeUpdate();
System.out.println("id\ttitle\tcreateTime");
pst = con.prepareStatement("select id,title,created_time from blog where id = ?");
pst.setInt(1, 1);
ResultSet rs = pst.executeQuery();
if (rs.next()) {
System.out.println(rs.getInt(1) + "\t" + rs.getString(2).trim() + "\t" + rs.getDate(3));
}
} catch (Exception e) {
System.err.println(e);
} finally {
try {
if (pst != null) {
pst.close();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
输出结果:
id title createTime
1 I love Java 2011-05-11
数据库中也有相应的数据被插入了,只是程序的设值不合理。。。
14.调用存储过程
java.sql.CallableStatement接口提供了调用数据库服务器端存储过程(Procedure)的功能,它继承了java.sql. PreparedStatement接口。
Connection 对象的prepareCall(String sql) 方法可创建并返回CallableStatement对象。
CallableStatement接口主要方法:
void setXXX(int parameterIndex, XXX x)
boolean execute()
采用存储过程可以提高系统的运行效率,但是在数据库移植的时候会产生一些错误或者加重移植的操作任务
实例:
首先建立一个存储过程:
drop procedure MyProcedure;
drop table person;
create table person(id number primary key, name char(20), age number);
create or replace procedure MyProcedure (pid in number,name in char,age in char)
as
begin
insert into person values(pid,name,age);
end;
/
测试类:
import java.sql.*;
public class CallStmt{
public static void main(String[] args){
Connection con = null;
CallableStatement cst = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
con = DriverManager.getConnection(url,"scott","tiger");
cst = con.prepareCall("{call MyProcedure(?,?,?)}");
cst.setInt(1,1001);
cst.setString(2,"Jenny");
cst.setInt(3,48);
cst.execute();
cst.close();
}catch(Exception e){
System.err.println(e);
}finally{
try{
if(con != null){
con.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
15.事务处理
(1)和数据库中的事务管理模式相对应,JDBC 中的Connection对象也可分为自动提交和非自动提交两种模式。
JDBC驱动程序的默认事务管理模式为"自动提交"。
Connection接口提供的事务处理相关方法:
void setAutoCommit(boolean autoCommit):默认是true
boolean getAutoCommit():得到当前的提交方式
void commit():commit和rollback是在关闭了自动提交时才会有的方法
void rollback()
测试实例:
import java.sql.*;
public class TestCommit{
public static void main(String args[]){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url="jdbc:oracle:thin:@127.0.0.1:1521:ora9";
conn=DriverManager.getConnection(url,"scott","tiger");
boolean autoCommit = conn.getAutoCommit();
// 关闭自动提交功能
conn.setAutoCommit(false);
Statement stmt=conn.createStatement();
stmt.executeUpdate("insert into dept values (77,'Market','Beijing')");
stmt.executeUpdate("insert into dept values (88,'R&D','Shanghai')");
ResultSet rs=stmt.executeQuery("select * from dept");
while(rs.next()){
System.out.print("DeptNo: "+rs.getInt(1));
System.out.print("\tDeptName: "+rs.getString(2));
System.out.println("\tLOC: "+rs.getString(3));
}
// 提交事务
conn.commit();
// 恢复原来的提交模式
conn.setAutoCommit(autoCommit);
stmt.close();
}catch(Exception e){
System.out.println("操作失败、任务撤消!");
try{
// 回滚、取消前述操作
conn.rollback();
}catch(Exception e1){
e.printStackTrace();
}
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
(2)事务处理之部分回滚
JDBC3.0 开 始 支 持 在 事 务 中 使 用 保 存 点(Savepoint),以实现对数据库事务的进一步控制、即支持部分回滚功能。
java.sql.Savepoint接口表示数据库事务中的保存点。
在Connection对象的rollback()方法中可以对当前事中的保存点进行引用,从而将事务回滚到该保存点。
在保存点之前的更新操作能生效,但是之后的更新不生效。
代码实例:
import java.sql.*;
public class TestSavepoint{
public static void main(String[] args){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url,"scott","tiger");
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.executeUpdate("insert into teacher values(11,'Tom',2500)");
stmt.executeUpdate("insert into teacher values(12,'John',3400)");
Savepoint sp1 = conn.setSavepoint("p1");
stmt.executeUpdate("insert into teacher values(13,'Billy',3150)");
Savepoint sp2 = conn.setSavepoint("p2");
stmt.executeUpdate("update teacher set salary = salary+8888 where tid = 12");
ResultSet rs = stmt.executeQuery("select avg(salary) from teacher");
rs.next();
double avg_sal = rs.getDouble(1);
if(avg_sal > 4000){
conn.rollback(sp1);
}else if(avg_sal >= 3000){
conn.rollback(sp2);
}
conn.commit();
rs = stmt.executeQuery("select * from teacher");
while(rs.next()){
System.out.println(rs.getInt(1) + "\t" + rs.getString(2).trim() + "\t" + rs.getDouble(3));
}
rs.close();
stmt.close();
}catch(Exception e){
System.out.println("Failure,rollback!");
try{
conn.rollback();
}catch(Exception e1){
e.printStackTrace();
}
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
16.批处理
JDBC2.0 开 始 提 供 了 对 数 据 库 操 作 的 批 处 理(Batch Processing)功能,使用批处理功能避免了向数据库进行一连串的调用,
从而可以显著提高程序的运行效率。
Statement接口提供的批处理相关方法:
void addBatch(String sql)
int[] executeBatch()
void clearBatch()
实例代码:
import java.sql.*;
public class TestBatch{
public static void main(String[] args){
Connection conn = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url,"scott","tiger");
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
stmt.addBatch("insert into teacher values(11,'Tom',2500)");
stmt.addBatch("insert into teacher values(12,'John',3400)");
stmt.addBatch("insert into teacher values(13,'Billy',3150)");
stmt.addBatch("update teacher set salary = salary + 88");
stmt.executeBatch();
conn.commit();
ResultSet rs = stmt.executeQuery("select * from teacher");
while(rs.next()){
System.out.println(rs.getInt(1) + "\t" + rs.getString(2).trim() + "\t" + rs.getDouble(3));
}
rs.close();
stmt.close();
}catch(Exception e){
System.out.println("Failure,rollback!");
try{
conn.rollback();
}catch(Exception e1){
e.printStackTrace();
}
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
17.高级SQL类型 BLOB/CLOB
BLOB(Binary Large OBject,二进制大对象)类型用于保存大规模的二进制数据
CLOB(Character Large OBject,文本大对象)类型则用于保存大规模的文本数据
JDBC2.0开始引入了对应于SQL99标准的多种高级数据类型,其中最重要的是两种大对象类型BLOB和CLOB
要在Oracle数据库中使用这两种大对象类型必须要使用高版本的数据库驱动程序
测试实例:
保存Blob
import java.sql.*;
import java.io.*;
public class SavePicture{
public static void main(String[] args){
Connection conn = null;
PreparedStatement stmt = null;
FileInputStream fis = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url, "scott","tiger");
String sql = "insert into Student_List values(?,?,?)";
stmt=conn.prepareStatement(sql);
stmt.setString(1,"s01");
stmt.setString(2,"Youyou");
File file = new File("yy.jpg");
fis = new FileInputStream(file);
stmt.setBinaryStream(3, fis, (int)file.length());
stmt.executeUpdate();
stmt.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fis!=null){
fis.close();
}
}catch(IOException ioe){
ioe.printStackTrace();
}
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
得到BLOB
import java.sql.*;
import java.io.*;
public class GetPicture{
public static void main(String[] args){
PreparedStatement stmt = null;
ResultSet rs = null;
Connection conn = null;
FileOutputStream fos = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url= "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url,"scott","tiger");
String sql="select * from Student_List where Student_ID='s01'";
stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery();
rs.next();
File file = new File("d:\\kk.jpg");
fos = new FileOutputStream(file);
InputStream is = rs.getBinaryStream(3);
int len = 0;
byte b[] = new byte[4*1024];
while((len=is.read(b))!=-1)
{
fos.write(b,0,len);
}
fos.flush();
fos.close();
is.close();
rs.close();
stmt.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fos!=null){
fos.close();
}
}catch(IOException ioe){
ioe.printStackTrace();
}
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
保存CLOB
import java.sql.*;
import java.io.*;
public class SaveClob{
public static void main(String[] args){
Connection conn = null;
PreparedStatement stmt = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url, "scott","tiger");
String sql = "insert into book_list values(?,?,?)";
stmt=conn.prepareStatement(sql);
stmt.setString(1,"b001");
stmt.setString(2,"99个简单法则");
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
StringBuffer sb = new StringBuffer();
String s;
while((s=br.readLine()) != null){
sb.append(s + "\n");
}
br.close();
String content = sb.toString();
StringReader sr = new StringReader(content);
stmt.setCharacterStream(3, sr, content.length());
stmt.executeUpdate();
sr.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
得到CLOB
import java.sql.*;
import java.io.*;
public class GetClob{
public static void main(String[] args){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
FileOutputStream fos = null;
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
String url= "jdbc:oracle:thin:@localhost:1521:ora9";
conn = DriverManager.getConnection(url,"scott","tiger");
String sql="select * from book_list where bid='b001'";
stmt = conn.prepareStatement(sql);
rs = stmt.executeQuery();
rs.next();
StringBuffer sb = new StringBuffer();
Reader rd = rs.getCharacterStream(3);
BufferedReader br = new BufferedReader(rd);
String s;
while((s=br.readLine())!=null)
{
sb.append(s + "\n");
}
System.out.println(sb.toString());
rs.close();
br.close();
stmt.close();
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(conn != null){
conn.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}