Java系列(二十一)__JDBC
1、JDBC简介
JDBC指的是Java数据库连接,可以直接利用Java程序进行各种数据库连接及操作。JDBC在Java之中属于一个服务的概念,所谓的服务指的就是一组固定的类库以完成某些固定的操作,而所有的服务在使用的形式上都很固定。
那么在进行JDBC操作的过程之中,重点在于数据库的连接上,而对于JDBC的连接主要可以见到三种:
· JDBC-ODBC桥连接:使用微软提供的ODBC技术进行数据库的连接,由于其是Java本身所支持的,所以版本永远是最新的,但是永远也是没人用的;
|- 操作形式:程序 è JDBC è ODBC è 数据库,性能很差;
· JDBC连接:由各个数据库的生产商提供有数据库的驱动程序(根据JDBC标准开发的),由于其直接使用Java连接,所以性能较高;
|- 操作形式:程序 è JDBC è 数据库,性能较高;
· 网络连接:通过网络协议连接网络上的数据库服务,这样的方式是开发之中主要使用的。
在java.sql包之中提供有所有的JDBC开发类的支持,常用的:DriverManager类、Connection接口、Statement接口、PreparedStatement接口、ResultSet接口。
2、JDBC连接Oracle数据库
本次要连接的是Oracle数据库,所以必须首先启动Oracle的两个重要服务(监听、实例服务),随后还需要配置Oracle数据库的驱动程序。Oracle和DB2的驱动程序都是随着安装包提供的。
· 路径:D:\app\Teacher\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6_g.jar
一切准备工作就绪之后,就可以给出JDBC操作数据库的标准流程:
· 第一步:加载数据库驱动程序;
|- 驱动程序的加载主要是向容器之中加载,通过Class.forName()加载;
|- Oracle的驱动程序名称:oracle.jdbc.driver.OracleDriver;
· 第二步:根据给定的数据库连接地址、用户名、密码连接数据库;
|- 连接需要的主要信息:
|- 连接地址:jdbc:oracle:thin:@主机名称:端口号:SID;
|- 连接mldn:jdbc:oracle:thin:@localhost:1521:MLDN;
|- 用户名:scott;
|- 密码:tiger;
|- 连接数据库主要是利用DriverManager类完成,取得的连接对象使用Connection接口表示;
· 第三步:打开数据库连接之后可以通过SQL进行数据库操作;
|- 数据库的操作主要是CRUD,利用Statement、PreparedStatement、ResultSet操作SQL语句;
· 第四步:数据库属于资源操作,操作的最后一定要使用close()方法关闭
|- Connection、Statement、PreparedStatement、ResultSet都提供有关闭方法。
由于JDBC是一个开发标准,所以来讲在JDBC之中,每一个数据库连接都使用一个Connection接口表示(一个数据库可以打开多个连接,那么就使用多个Connection接口对象表示)。而所有的连接都需要通过DriverManager类打开,此类定义了如下方法:
· 连接数据库:public static Connection getConnection(String url, String user, String password)
throws SQLException;
范例:连接数据库
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 System.out.println(conn); // 如果不为null表示已连接 conn.close() ; } } |
那么通过以上的程序就可以发现,只要是想取得数据库的连接必须使用DriverManager类,那么今天连接的是Oracle,有可能明天连接的是mysql,或者是世界上近千种数据库,那么在连接的时候,只要遵守了JDBC的开发标准,都可以采用之前完全相同的方式进行连接,于是现在的代码就行成了这样的结构。
所以DriverManager类严格来讲就是一个工厂类,通过此类之中的getConnection()方法,只要传入了正确的连接地址、用户名、密码,就可以取得一个指定的Connection接口对象(这个时候Connection子类完全是由各个数据库生产商根据Connection接口标准制定的。)
所谓的数据库连接对数据库而言实际上就是程序建立了若干个Socket连接而已。
3、Statement
当取得了Connection接口对象之后,下面就可以利用Connection打开数据库的操作接口Statement,在Connection接口里面定义有一个取得Statement接口对象的方法:public Statement createStatement() throws SQLException。
而取得了Statement接口后就可以进行两类操作:
· 数据库更新操作:public int executeUpdate(String sql) throws SQLException,返回更新行数;
· 数据库查询操作:public ResultSet executeQuery(String sql) throws SQLException。
范例:编写数据库创建脚本
-- 删除对象 DROP SEQUENCE myseq ; DROP TABLE member ; -- 创建对象 CREATE SEQUENCE myseq ; CREATE TABLE member ( mid NUMBER , name VARCHAR2(20) NOT NULL , birthday DATE , note CLOB , CONSTRAINT mid_pk PRIMARY KEY(mid) ) ; |
下面将使用Statement实现数据库操作。但是Statement使用的是标准SQL语句,所以对于日期的处理要使用TO_DATE()函数。
3.1、实现更新操作
更新操作一共分为三类:增加、修改、删除。
范例:增加新数据
· SQL语法:INSERT INTO 表名称(字段,字段,…) VALUES (值 , 值 , …) ;
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; // 创建Statement对象 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " INSERT INTO member(mid,name,birthday,note) " + " VALUES (myseq.nextval,'小刁大笨', " + " TO_DATE('1911-11-11','yyyy-mm-dd'),'笨的没人样了。。。天生神棍') " ; int len = stmt.executeUpdate(sql) ; // 执行SQL System.out.println("更新行数:" + len); conn.close() ; } } |
范例:修改数据
· SQL语法:UPDATE 表名称 SET 字段=值, … WHERE 修改条件;
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; // 创建Statement对象 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " UPDATE member SET name='小谢子',note='小刁子很吊,好贱', " + " birthday=SYSDATE WHERE mid IN (5,7,9,10,20) " ; int len = stmt.executeUpdate(sql) ; // 执行SQL System.out.println("更新行数:" + len); conn.close() ; } } |
范例:删除数据
· SQL语法:DELETE FROM 表名称 WHERE 删除条件;
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; // 创建Statement对象 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " DELETE FROM member WHERE mid IN (2,4,6,8,10) " ; int len = stmt.executeUpdate(sql) ; // 执行SQL System.out.println("更新行数:" + len); conn.close() ; } } |
这个时候可以清楚的发现,整个操作过程之中,唯一改变的只是SQL语句。
3.2、实现查询操作
更新操作主要是返回更新的数据行数,但是如果是查询操作,则需要把查询结果返回,而查询结果一般都是以“行、列集合”的形式返回的,所以就必须有一种结构,可以容纳这些行和列,于是就有了ResultSet接口,即:所有查询的返回值都保存在了ResultSet集合之中。
范例:查询数据
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Date; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; // 创建Statement对象 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " SELECT mid,name,birthday,note FROM member " ; ResultSet rs = stmt.executeQuery(sql) ; // 执行查询操作 // 每次循环是操作返回的一行记录 while (rs.next()) { // 移动游标,同时判断是否有数据 int mid = rs.getInt("mid") ; String name = rs.getString("name") ; Date birthday = rs.getDate("birthday") ; String note = rs.getString("note") ; System.out.println(mid + "," + name + "," + birthday + "," + note); } conn.close() ; } } |
但是很多的时候在进行列访问的时候也会采用索引的形式取得数据。
while (rs.next()) { // 移动游标,同时判断是否有数据 int mid = rs.getInt(1) ; String name = rs.getString(2) ; Date birthday = rs.getDate(3) ; String note = rs.getString(4) ; System.out.println(mid + "," + name + "," + birthday + "," + note); } |
在日后编写SQL的时候明确的写上列名称,而后就可以利用索引来取得数据,这是最为常用的方式。
4、PreparedStatement
虽然可以利用Statement操作数据库,但是如果在开发之中,Statement是不可能使用的,以增加数据为例,在本表之中姓名、生日、介绍应该由用户自己输入。
范例:问题引出
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { String name = "Mr'SMITH" ; String birthday = "2012-12-25" ; String note = "荒唐的世界末日" ; Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; // 创建Statement对象 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " INSERT INTO member(mid,name,birthday,note) " + " VALUES (myseq.nextval,'"+name+"', " + " TO_DATE('"+birthday+"','yyyy-mm-dd'),'"+note+"') " ; System.out.println(sql); int len = stmt.executeUpdate(sql) ; // 执行SQL System.out.println("更新行数:" + len); conn.close() ; } } |
INSERT INTO member(mid,name,birthday,note) VALUES (myseq.nextval,'Mr'SMITH', TO_DATE('2012-12-25','yyyy-mm-dd'),'荒唐的世界末日') |
Exception in thread "main" java.sql.SQLSyntaxErrorException: ORA-00917: 缺失逗号 |
此时的程序中由于SQL需要拼凑的原因,那么用户一旦输入了一些敏感的字符,就有可能造成错误,严重的就有可能出现严重的安全漏洞,所以就得出结论:拼凑的SQL不能用。
在实际的开发之中永恒不会有人去使用Statement,而都使用Statement的子接口:PreparedStatement(预处理)。提升操作的性能。那么现在如果要使用PreparedStatement接口,则就必须通过Connection接口中的新方法实例化对象:
· 方法:public PreparedStatement prepareStatement(String sql) throws SQLException ;。
当取得了PreparedStatement接口对象之后,就可以利用新的方法操作:
· 更新操作:public int executeUpdate() throws SQLException;
· 查询操作:public ResultSet executeQuery() throws SQLException。
而最为重要的是,在创建PreparedStatement的时候所需要设置的内容都要通过一个占位符“?”表示,而在执行更新和查询之前,需要使用一系列的setXxx()方法设置“?”的数据。
但是在进行setDate()方法操作的时候需要注意一点:操作的是java.sql.Date,而不是java.util.Date。java.sql.Date是java.util.Date的子类,而在java.util.Date下一共有三个子类,而且这三个子类都是保存在java.sql包之中:Date(保存日期)、Time(保存时间)、TimeStamp(时间戳,日期 + 时间)。
范例:实现数据增加
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.util.Date; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { String name = "Mr'SMITH" ; Date birthday = new Date() ; String note = "荒唐的世界末日" ; Connection conn = null; // 每一个Connection对象都表示一个连接 PreparedStatement pstmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " INSERT INTO member(mid,name,birthday,note) " + " VALUES (myseq.nextval,?,?,?) " ; pstmt = conn.prepareStatement(sql) ; // 创建PreparedStatement接口对象 pstmt.setString(1, name); pstmt.setDate(2, new java.sql.Date(birthday.getTime())); pstmt.setString(3, note); int len = pstmt.executeUpdate() ; // 执行SQL System.out.println("更新行数:" + len); conn.close() ; } } |
在开发之中为了保证更新的质量,所有的操作一定使用的是PreparedStatement,以上做的只是一个增加(修改和删除也一样),而重点在于下面的查询操作上。
范例:查询全部数据
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 PreparedStatement pstmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " SELECT mid,name,birthday,note FROM member " ; pstmt = conn.prepareStatement(sql) ; ResultSet rs = pstmt.executeQuery() ; while (rs.next()) { int mid = rs.getInt(1) ; String name = rs.getString(2) ; Date birthday = rs.getDate(3) ; String note = rs.getString(4) ; System.out.println(mid + "," + name + "," + birthday + "," + note); } conn.close() ; } } |
范例:根据编号查询,查询指定编号的数据,此时只会返回单行多列数据。
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { int mid = 15 ; // 查询数据 Connection conn = null; // 每一个Connection对象都表示一个连接 PreparedStatement pstmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " SELECT mid,name,birthday,note " + " FROM member WHERE mid=?" ; pstmt = conn.prepareStatement(sql) ; pstmt.setInt(1, mid); ResultSet rs = pstmt.executeQuery() ; if (rs.next()) { mid = rs.getInt(1) ; String name = rs.getString(2) ; Date birthday = rs.getDate(3) ; String note = rs.getString(4) ; System.out.println(mid + "," + name + "," + birthday + "," + note); } else { System.out.println("没有数据返回!"); } conn.close() ; } } |
范例:模糊查询
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { String keyWord = "谢" ; Connection conn = null; // 每一个Connection对象都表示一个连接 PreparedStatement pstmt = null ; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = " SELECT mid,name,birthday,note " + " FROM member WHERE name LIKE ?" ; pstmt = conn.prepareStatement(sql) ; pstmt.setString(1, "%" + keyWord + "%"); // 在此写% ResultSet rs = pstmt.executeQuery() ; while (rs.next()) { int mid = rs.getInt(1) ; String name = rs.getString(2) ; Date birthday = rs.getDate(3) ; String note = rs.getString(4) ; System.out.println(mid + "," + name + "," + birthday + "," + note); } conn.close() ; } } |
如果在执行模糊查询的时候不设置任何的关键字,表示查询全部。
范例:分页显示
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.Date; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { int currentPage = 2; int lineSize = 5; String keyWord = ""; Connection conn = null; // 每一个Connection对象都表示一个连接 PreparedStatement pstmt = null; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = "SELECT * FROM (" + " SELECT mid,name,birthday,note,ROWNUM rn " + " FROM member WHERE name LIKE ? AND ROWNUM<=?) temp " + " WHERE temp.rn>? "; pstmt = conn.prepareStatement(sql); pstmt.setString(1, "%" + keyWord + "%"); // 在此写% pstmt.setInt(2, currentPage * lineSize); pstmt.setInt(3, (currentPage - 1) * lineSize); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { int mid = rs.getInt(1); String name = rs.getString(2); Date birthday = rs.getDate(3); String note = rs.getString(4); System.out.println(mid + "," + name + "," + birthday + "," + note); } conn.close(); } } |
范例:统计数据行
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { String keyWord = ""; Connection conn = null; // 每一个Connection对象都表示一个连接 PreparedStatement pstmt = null; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 // 如果在编写SQL过程之中出现换行,请一定要保证前后各加一个空格 String sql = "SELECT COUNT(mid) FROM member WHERE name LIKE ?"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, "%" + keyWord + "%"); // 在此写% ResultSet rs = pstmt.executeQuery(); if (rs.next()) { // 永恒有数据返回 System.out.println(rs.getInt(1)); } conn.close(); } } |
以上所给出的几个基本的数据库操作,一定要拿下,明天就要用。
5、批处理与事务处理
以上所使用的开发模式是JDBC 1.0提出来的,而现在的JDBC的版本是4.0(没人用),而且从JDBC 2.0开始就已经提出了许多新的特征:可滚动结果集、使用结果集更新数据、批处理,这之中唯一有点用处的就是批处理操作,所谓的批处理指的是一次性向数据库之中发出多条更新指令,在Statement和PreparedStatement接口里面都有对应的方法:
· Statement接口定义的方法:
|- 增加批处理语句:public void addBatch(String sql) throws SQLException;
|- 执行批处理:public int[] executeBatch() throws SQLException;
|- 返回的是每一条SQL语句影响的数据行数量
· PreparedStatement接口定义的方法:
|- 增加批处理:public void addBatch() throws SQLException。
范例:利用Statement来观察问题
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); int result [] = stmt.executeBatch() ; for (int x = 0 ; x < result.length ; x ++) { System.out.print(result[x] + "、"); } conn.close(); } } |
但是如果说现在有这样一种情况,以上五个要执行SQL语句属于一个完整业务,即:要求所有的SQL一起成功或者是一起失败。但是默认情况下,JDBC中的事务都是自动提交的,所以如果中间出现了错误,那么之前没有错的正常执行,很明显这不符合要求,所以必须手工的进行事务处理,而所有的事务处理命令都在Connection接口中定义:
· 提交事务:public void commit() throws SQLException;
· 回滚事务:public void rollback() throws SQLException;
· 设置自动提交与否:public void setAutoCommit(boolean autoCommit) throws SQLException。
范例:使用事务处理
package cn.mldn.demo; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; public class TestDemo { private static final String DBDRIVER = "oracle.jdbc.driver.OracleDriver"; private static final String DBURL = "jdbc:oracle:thin:@localhost:1521:mldn"; private static final String DBUSER = "scott"; private static final String PASSWORD = "tiger"; public static void main(String[] args) throws Exception { Connection conn = null; // 每一个Connection对象都表示一个连接 Statement stmt = null; // 定义数据库操作对象 Class.forName(DBDRIVER); // 加载数据库驱动程序 conn = DriverManager.getConnection(DBURL, DBUSER, PASSWORD); // 连接数据库 stmt = conn.createStatement() ; conn.setAutoCommit(false);// 取消自动提交 try { stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); stmt.addBatch("INSERT INTO member(mid,name) VALUES (myseq.nextval,'张三')"); int result [] = stmt.executeBatch() ; for (int x = 0 ; x < result.length ; x ++) { System.out.print(result[x] + "、"); } conn.commit(); // 提交事务 } catch (Exception e) { e.printStackTrace(); conn.rollback(); } conn.close(); } } |
因为日后的开发之中,事务都是自动处理的,用户只需要编写代码就行了。