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();
}
}
}


转载: java连接常见数据库的连接字符串

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();
}
}
}
}

JavaEE之JDBC编程[详解]的更多相关文章

  1. Log4J:Log4J三大组件:Logger+Appender+Layout 格式化编程详解

    快速了解Log4J Log4J的三个组件: Logger:日志记录器,负责收集处理日志记录     (如何处理日志) Appender:日志输出目的地,负责日志的输出  (输出到什么 地方) Layo ...

  2. ORACLE PL/SQL编程详解

    ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...

  3. Linux串口编程详解(转)

    串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...

  4. [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

    原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...

  5. [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)

    原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...

  6. 【强烈强烈推荐】《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航

    原文:[强烈强烈推荐]<ORACLE PL/SQL编程详解>全原创(共八篇)--系列文章导航 <ORACLE PL/SQL编程详解> 系列文章目录导航 ——通过知识共享树立个人 ...

  7. [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)

    原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下 ...

  8. [顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功)

    原文:[顶]ORACLE PL/SQL编程详解之二:PL/SQL块结构和组成元素(为山九仞,岂一日之功) [顶]ORACLE PL/SQL编程详解之二: PL/SQL块结构和组成元素(为山九仞,岂一日 ...

  9. Java的JDBC事务详解

    Java的JDBC事务详解         分类:             Hibernate              2010-06-02 10:04     12298人阅读     评论(9) ...

随机推荐

  1. The Cow Lexicon POJ - 3267 dp

    题意  给出一个母串  和一个字典 问母串最少删去几个字母     删去后的母串是由字典里面的单词拼起来的 思路:dp[i]表示从i到母串结尾最少需要删除多少个字母  初始化dp[length]=0 ...

  2. Girls and Boys HDU - 1068 二分图匹配(匈牙利)+最大独立集证明

    最大独立集证明参考:https://blog.csdn.net/qq_34564984/article/details/52778763 最大独立集证明: 上图,我们用两个红色的点覆盖了所有边.我们证 ...

  3. Codeforces1023E Down or Right 【贪心】

    题目分析: 从起点开始询问终点连通性,优先右走.从终点开始询问起点连通性,优先上走. 代码: #include<bits/stdc++.h> using namespace std; in ...

  4. Awesome-VR

    Google-tool Marzipano是现代网络的360°媒体查看器.—— Google官网  文档   案例    源码 WebVR-Frameworks ReactVR - Build VR ...

  5. emwin 存在多个窗口时,如何获取当前所在窗口

    @2019-02-20 [小记] emwin存在多个窗口时,如何获取当前所在窗口 > emwin 之获取当前窗口的一种方法 [需求] 用于在代码中获知当前呈现的是哪个窗口 [方法] 进入新窗口将 ...

  6. attr prop jquery关于获取DOM属性值的两个函数

    $('#domid').attr('acitve') $('#domid').prop('checked') // 在使用JQUERY获取DOM元素的属性时,有两个函数,attr 和 prop < ...

  7. ES6中箭头函数与普通函数this的区别

    普通函数中的this: 1. this总是代表它的直接调用者, 例如 obj.func ,那么func中的this就是obj 2.在默认情况(非严格模式下,未使用 'use strict'),没找到直 ...

  8. luogu5024 [NOIp2018]保卫王国 (动态dp)

    可以直接套动态dp,但因为它询问之间相互独立,所以可以直接倍增记x转移到fa[x]的矩阵 #include<bits/stdc++.h> #define CLR(a,x) memset(a ...

  9. HDU 6336 Matrix from Arrays (杭电多校4E)

    遇事不决先打表. 然后会发现(个屁)大的矩形是由一个2L*2L的矩形重复出现组成的然后我们就可以这个矩形分成四个点到(0, 0)点的矩形,这样问题就变成了求四个到顶点(0, 0)的矩形的面积,然后就先 ...

  10. LVS+Keepalived搭建高可用负载均衡

    应用环境: LVS负责多台WEB端的负载均衡(LB):Keepalived负责LVS的高可用(HA),这里介绍主备模型. 测试环境: 配置步骤: 1. 安装软件 在LVS-1和LVS-2两台主机上安装 ...