七、 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();
}
}
}
}
}
View Code
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();
}
}
}
}
}
View Code
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
View Code
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();
}
}
}
}
}
View Code
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();
}
}
}
}
}
View Code
6. 数据库连接池
网上资料:https://www.cnblogs.com/xdp-gacl/p/4002804.html