1.什么是JDBC
-1.JDBC(Java Database Connection)为Java开发者使用数据库提供了统一的编程接口,它由一组Java类和接口组成。是Java程序与数据库通信的标准API。
JDBC API使得开发人员可以使用纯Java的方式来连接数 据库,并执行操作。
-2.sun公司由于不知道各个主流商用数据库的程序代码,因此无法自己写代码连接各个数据库,因此,sun公司自己提供了一套API,只要数据库想要和Java连接的,
数据库厂商必须自己实现JDBC这套接口。而数据库厂商的JDBC实现,我们就叫它此数据库的驱动。
2.JDBC访问数据库流程
1.加载JDBC驱动程序
2.建立与数据库的连接
3.发送SQL语句
4.得到SQL执行结果
3.Java程序和数据库连接的时候,其实就是Socket连接。
4.JDBC常用接口
Driver接口
- Driver接口由数据库厂家提供,对于Java开发者而言,只需要使用Driver接口就可以了。
- 在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序。不同的数据库有不同的装载方法。
- 驱动:就是各个厂商实现Sun公司提出的JDBC接口。即对Connection等接口的实现类的jar文件。
- 装载mysql驱动:Class.forName("com.mysql.jdbc.Driver");
- 装载oracle驱动:Class.forName("com.jdbc.driver.OracleDriver");
DriverManager接口
- DriverManager接口是JDBC的管理层,作用于用户和驱动程序之间。
- DriverManager跟踪可用的驱动程序,并在数据库和相应的驱动之间建立连接。
Connection接口
- Connection与特定数据库的连接(会话),在连接上下文中执行SQL语句并返回结果。
- DriverManager的getConnection()方法建立在JDBC URL中定义的数据库Connection连接上
-Mysql
Connection con = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
-Oracle
Connection con = DriverManager.getConnection("jdbc:oracle:thin@host:port/database", "user", "password");
Statement接口
- 用于执行静态SQL语句并返回它所生成结果的对象。
- 三种Statement类:
- Statement:
由createStatement创建,用于发送简单的SQL语句(不带参数)
- PreparedStatement:
- 继承自Statement接口,有preparedStatement创建,用于发送含有一个或者多个输入参数的SQL语句。PreparedStatement对象
比Statement对象效率更高,并且是防止SQL注入。我们一般都使用PreparedStatement。
- CallableStatement:
- 继承自preparedStatement。由方法prePareCall创建,用于调用存储过程。
- 常用的Statement方法
- execute():运行语句,返回是否有结果集。
- executeQuery():运行select语句,返回ResultSet结果节
- executeUpdate():运行insert/update/delete操作,返回更新的行数。
- 例子:
package com.yf.jdbc.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; /** * 测试执行SQL语句和SQL注入问题 * @author yangf * */ public class Demo02 { public static void main(String[] args) { try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得connection对象 建立与数据库连接 /* * 连接对象内部其实包含了Socket对象,是一个远程连接。比较耗时!这是Connection对象管理的一个要点。 * 后面通过连接池来做 */ Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); Statement stmt = con.createStatement(); String sql = "insert into t_user (username,pwd,regTime) values ('yyy',123123,now())"; stmt.execute(sql); String sql1 = "delete from t_user where id = 4"; stmt.execute(sql1); // 测试SQL注入 // 由于是外部传入参数,所以可以任意修改DB,造成SQL注入,所以我们不适用Statement String id = "5 or 1 = 1"; String sql2 = "delete from t_user where id = " + id; stmt.execute(sql2); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }
package com.yf.jdbc.test; import java.sql.Connection; import java.sql.Date; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; /** * 测试PreparedStatement的基本用法 * @author yangf * */ public class Demo03 { public static void main(String[] args) { try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得connection对象 建立与数据库连接 Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); String sql = "insert into t_user (username,pwd,regTime) values (?,?,?)"; PreparedStatement ps = con.prepareStatement(sql); ps.setString(1, "yangf"); ps.setInt(2, 888888); ps.setDate(3, new Date(System.currentTimeMillis())); ps.execute(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } }
ResultSet接口
- Statement执行SQL语句时返回Result结果集。
- ResultSet提供的检索不同类型字段的方法,常用的有:
- getString():获得在数据库里是varchar,char等数据类型的对象。
- getFloat():获得数据库里是Float类型的对象
- getDate():获得数据库里是Date类型的对象
- getBoolean():获得数据库里是Boolean类型的数据
- 依序关闭使用的对象和连接
Result->Statement->Connection
/** * 测试ResultSet的用法 * @author ibm * */ public class Demo04 { public static void main(String[] args) { Connection con = null; PreparedStatement ps = null; ResultSet rs = null; try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得connection对象 建立与数据库连接 con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); String sql = "select * from t_user where id > ?"; ps = con.prepareStatement(sql); ps.setInt(1, 2); // 内部就是个迭代器 rs = ps.executeQuery(); while (rs.next()) { System.out.println(rs.getInt(1) + "--" + rs.getString(2) + "--" + rs.getInt(3) + "--" + rs.getDate(4)); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if (ps != null) { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
批处理
- batch
- 对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限,数据量特别大时,会发生异常。
package com.yf.jdbc.test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * 测试批处理 * @author yangf * */ public class Demo05 { public static void main(String[] args) { Connection con = null; Statement stmt = null; ResultSet rs = null; try { // 加载数据库驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得connection对象 建立与数据库连接 con = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc", "root", "123456"); // jdbc中事物是自动提交的,我们设为手动提交 con.setAutoCommit(false); long start = System.currentTimeMillis(); stmt = con.createStatement(); for (int i = 0; i < 20000; i++) { stmt.addBatch("insert into t_user (username,pwd,regTime) values ('yangf "+ i + "', 6666 , now())"); } stmt.executeBatch(); con.commit(); long end = System.currentTimeMillis(); System.out.println("插入20000万条数据耗时:" + (end - start) + "毫秒"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (rs != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if (con != null) { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }