七、 JDBC
1. JDBC
/** * JDBC(Java DataBase Connectivity) * JDBC 访问数据库流程: * 1)加载 JDBC 驱动程序--> * 2)建立与数据库的连接 * (连接对象内部其实包含了 Socket 对象,是一个远程的连接。比较耗时!这是 Connection 对象管理的一个要点!!!)--> * 3)发送 SQL 语句查询--> * 4)得到查询结果 * * 1.Driver 接口: * 驱动:就是各个数据库厂商实现 SUN 公司提出的 JDBC 接口。即对 Connection 等接口的实现类的 Jar 文件(mysql-connector-java-5.1.47-bin.jar) * 装载 MySQL 驱动: * Class.forName("com.mysql.jdbc.Driver"); * 装载 Oracle 驱动: * Class.forName("oracle.jdbc.driver.OracleDriver"); * 2.DriverManager 接口: * -DriverManager 是 JDBC 的管理层,作用于用户和驱动程序之间 * -DriverManager 跟踪可用的驱动程序,并在数据库和相应的驱动程序之间建立联系 * * 3.Connection 接口: * -Connection 与特定数据库的连接,在连接上下文中执行 SQL 语句并返回结果 * -DriverManager 的 getConnection() 方法建立在 JDBC URL 中定义的数据库 Connnection 连接上 * -连接 MySQL 数据: * Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password"); * -连接 Oracle 数据库: * Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password"); * * 4.Statement 接口: * -用于执行静态的 SQL 语句并返回它所生成结果的对象 * -三种 Statement 类: * 1)Statement * -由方法 conn.createStatement(); 创建,不带参数,用于发送简单的 SQl 语句 * 2)PreparedStatement * -继承自 Statement 接口,由方法 conn.prepareStatement(sql); 创建,用来发送含有一个或多个输入参数的 SQl 语句。 * PreparedStatement 对象比 Statement 对象的效率更高,并且可以防止 SQL 注入。我们一般都用 PreparedStatement * 3)CallableStatement * -继承自 PreparedStatement,由方法 conn.prepareCall(sql); 创建,用于调用存储过程 * -常用的 Statement 方法 * execute();运行语句,返回是否有结果集 * executeQuery();运行 select 语句,返回 ResultSet 结果集 * executeUpdate();运行 insert/update/delete 操作,返回更新的行数 * * 5.ResultSet 接口: * -Statement 执行 SQL 语句返回 ResultSet 结果集 * -ResultSet 提供检索不同类型字段的方法,常用的有: * getString();获取在数据库里是 varchar、char 等数据类型的对象 * getInt(); * getDate(); * getBoolean(); * getFloat();
* getTimeStemp(); * * 6.解决乱码问题 * 使用 JDBC 往数据库内添加数据,没有 IO 流读取的步骤的话,并且在确认获取的数据没有乱码的情况下,最后一个环节可能是数据库本身的编码不是 UTF-8,使用: * "jdbc:mysql://localhost:3306/databaseName?characterEncoding=UTF-8" */
public class JDBC { public static void main(String arg[]){ Connection conn =null; PreparedStatement ps = null; ResultSet rs = null; try { // 1.加载 mysql 驱动: Class.forName("com.mysql.jdbc.Driver"); long start = System.currentTimeMillis(); // 2.建立连接(连接对象内部其实包含了 Socket 对象,是一个远程的连接.比较耗时!这是 Connection 对象管理的一个要点!!!) // 真正开发中,为了提高效率,都会使用连接池来管理连接对象 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/databaseName", "root", "hello"); long end = System.currentTimeMillis(); System.out.println(conn); System.out.println("建立连接,耗时:" + (end-start) + "ms毫秒"); // 3.创建 SQL 命令和 SQL 命令对象 String sql = "insert into t_user (uname,pwd) values(?,?)";// ?为占位符,防止SQL注入 ps = conn.prepareStatement(sql); // 4.给占位符赋值 // ps.setString(1, "Lisisi"); // ps.setString(2, "123456"); ps.setObject(1, "Lisisi"); ps.setObject(2, "123456"); // 5.执行 int count = ps.executeUpdate(); System.out.println(count); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally{ // 关闭资源,注意:后开的先关 ResultSet-->PreparedStatement-->Connection,一定要三个 try catch 分开写 if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
2. JDBC Transaction
/** * 事务基本概念: * -一组要么同时执行成功,要么同时执行失败的 SQL 语句,是数据库操作的一个执行单元 * -事务开始于: * 1)连接到数据库上,并执行一条 DML 语句(insert、update、delete) * 2)前一个事务结束后,又输入了另一条 DML 语句 * -事务结束于: * 1)执行 conn.commit(); 或 conn.rollback(); 语句 * 2)执行一条 DDL 语句,例如 create table 语句;这种情况下,会自动执行 conn.commit(); 语句 * 3)断开与数据库的连接 * 4)执行一条 DML 语句,该语句却失败;这种情况下,会为这个无效的 DML 语句执行 conn.rollback(); 语句 * * 事务的四大特点:(ACID) * 1)atomicity 原子性 * 2)consistency 一致性 * 3)isolation 隔离性 级别(由低到高):读取未提交--读取已提交(一般情况都是)--可重复读--序列化 * 4)durability 持久性 */
public class Transaction { public static void main(String arg[]){ Connection conn = null; PreparedStatement ps1 = null; PreparedStatement ps2 = null; ResultSet rs = null; try { //加载mysql驱动 Class.forName("com.mysql.jdbc.Driver"); //创建连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/wollo","root","hello"); conn.setAutoCommit(false);//设置手动提交事务 //创建SQL命令对象 ps1 = conn.prepareStatement("insert into t_user(uname,pwd) values(?,?)"); ps1.setString(1, "zhangsan"); ps1.setString(2, "123456"); //执行 ps1.executeUpdate(); System.out.println("插入第一条数据"); try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } //创建SQL命令对象 ps2 = conn.prepareStatement("insert into t_user(uname,pwd) values(?,?,?)"); ps2.setString(1, "lisisi"); ps2.setString(2, "123456"); //执行 ps2.executeUpdate(); System.out.println("插入第二条数据"); conn.commit();//提交 } catch (ClassNotFoundException e) { e.printStackTrace(); try { conn.rollback();//错误回滚 } catch (SQLException e1) { e1.printStackTrace(); } } catch (SQLException e) { e.printStackTrace(); }finally{ if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps2!=null){ try { ps2.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps1!=null){ try { ps1.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
3. JDBC Util
import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static Properties pros = null;// 可以帮助读取和处理资源文件中的信息 static{// 静态代码块,只有在加载 JDBCUtil 类的时候调用 pros = new Properties(); try { pros.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties")); } catch (IOException e) { e.printStackTrace(); } } public static Connection getMysqlConn(){ try { Class.forName(pros.getProperty("mysqlDriver")); Connection conn = DriverManager.getConnection(pros.getProperty("mysqlURL"),pros.getProperty("mysqlUser"),pros.getProperty("mysqlPwd")); return conn; } catch (SQLException e) { e.printStackTrace(); return null; } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } public static Connection getOracleConn(){ try { Class.forName(pros.getProperty("oracleDriver")); Connection conn = DriverManager.getConnection(pros.getProperty("oracelURL"),pros.getProperty("oracleUser"),pros.getProperty("oraclePwd")); return conn; } catch (SQLException e) { e.printStackTrace(); return null; } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } } public static void close(ResultSet rs,Statement ps,Connection conn){ try { if(rs!=null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(ps!=null){ ps.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(conn!=null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } public static void close(Statement ps,Connection conn){ try { if(ps!=null){ ps.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if(conn!=null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } /* db.properties */ mysqlDriver=com.mysql.jdbc.Driver mysqlURL=jdbc:mysql://localhost:3306/wollo?characterEncoding=utf-8 mysqlUser=root mysqlPwd=hello oracleDriver=oracle.jdbc.driver.OracleDriver oracleURL=jdbc:oracle:thin:@localhost:1521/XE oracleUser=system oraclePwd=hello
4. Batch
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; /** * 批处理: * -Batch * -对于大量 SQL 语句的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限,当数据量特别大的时候,会发生异常 */ public class Batch { public static void main(String arg[]){ Connection conn = null; Statement stmt = null; ResultSet rs = null; try { // 1.加载 mysql 驱动 Class.forName("com.mysql.jdbc.Driver"); // 2.建立数据库与驱动间的连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/wollo","root","hello"); conn.setAutoCommit(false);// 设为手动提交,jdbc 默认是 true,自动提交 long start = System.currentTimeMillis(); // 创建 SQL 命令对象 stmt = conn.createStatement(); for(int i=0; i<20000; i++){ String sql = "insert into t_user(uname,pwd) values('liao"+i+"',666666)"; stmt.addBatch(sql); } stmt.executeBatch(); conn.commit();// 提交事务 long end = System.currentTimeMillis(); System.out.println("插入两万条数据,耗时:"+(end-start)); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if(null!=rs){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null!=stmt){ try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } } if(null!=conn){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
5. BLOB & CLOB
/** * * CLOB文本大对象(Character Large Object) * -用于存储大量的文本数据 * -大字段有些特殊,不同数据库处理方式不一样,大字段的操作常常是"以流的方式"来处理的,而非一般的字段,一次即可读出数据 * * BLOB二进制大对象(Binary Large Object) * -用于存储大量的二进制数据 * -大字段有些特殊,不同数据库处理方式不一样,大字段的操作常常是"以流的方式"来处理的,而非一般的字段,一次即可读出数据 * */ import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.sql.Clob; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class CLOB { public static void main(String arg[]) throws IOException{ Connection conn = null; PreparedStatement ps = null; ResultSet rs = null; Reader r = null; try { //创建mysql驱动 Class.forName("com.mysql.jdbc.Driver"); //创建连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/wollo","root","hello"); //创建SQL命令对象 ps = conn.prepareStatement("insert into t_user(uname,pwd,myInf) values(?,?,?)"); ps.setString(1, "zhangsan"); ps.setString(2, "123456"); //将文本文件内容直接输入到数据库 // ps.setClob(3, new BufferedReader(new FileReader(new File("E:/test/b.java")))); //将程序中的字符串输入到数据库的CLOB字段中 ps.setClob(3, new BufferedReader(new InputStreamReader(new ByteArrayInputStream("aaaaaabbbbb".getBytes())))); ps.executeUpdate(); ps = conn.prepareStatement("select * from t_user where uid=?"); ps.setInt(1, 1); rs = ps.executeQuery(); while(rs.next()){ Clob c = rs.getClob("myInf"); r = c.getCharacterStream(); int len = 0; while((len=r.read())!=-1){ System.out.print((char)len); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally{ if(r!=null){ try { r.close(); } catch (Exception e) { e.printStackTrace(); } } if(rs!=null){ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } } if(ps!=null){ try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }