JDBC简介
Java Database Connectivity,即Java数据库连接。一种可以执行SQL语句的Java API。可以实现跨数据库,跨平台,具有非常优秀的移植性。
DDL:操作数据库对象的语句, 包括创建(ctrate)、删除(drop)、修改(alter)
DML:操作数据表里的数据,包括插入、修改、删除
JDBC完成的基本操作:
- 建立与数据库的连接
- 执行sql语句
- 获得sql语句的执行结果
JDBC驱动程序
数据库驱动程序:JDBC程序和数据库之间的转换层,数据库驱动程序负责将JDBC调用映射成特定的数据库调用。
JDBC驱动有四种:
- JDBC-ODBC桥
- 直接将JDBC API映射成数据库特定的客户端AP
- 支持三层架构的JDC 访问方式,主要用于Applet阶段,通过Applet访问数据库。
- 纯java,直接与数据库实例交互。是目前最流行的JDBC驱动。
JDBC 的典型用法
JDBC API:
- DriverManager:用于管理JDBC驱动的服务类。程序中使用该类的主要功能时获取Connection 对象,该类包含如下方法。
- public static synchronized Connection getConnection(String url,String user,String pass) throws SQLException:该方法获得url对应数据库的连接。
- Connection:代表数据库连接对象。每一个Connection代表一个物理连接会话。要想访问数据库,必须先获得数据库连接。该接口的常用方法如下:
- Statement createStatement() throws SQLExcetpion:该方法返回一个Statement 对象
- PreparedStatement() throws SQLExcetpion: 该方法返回编译的Statement 对象,即将SQL 语句提交到数据库进行预编译。
- CallableStatement prepareCall(String sql) throws SQLExcetpion:该方法返回CallableStatement 对象,该对象用于调用存储过程。
Connection 用于控制事物的方法:
-
Savepoint setSavepoint():创建一个保存点。
-
Savepoint setSavepoint(String name):用指定名字创建一个保存点。
-
void setTransactionIsolation(int level):设置事务的隔离级别。
-
void rollback():回滚事物。
-
void rollback(Savepoint savepoint):将事物回滚到指定的保存点。
-
void setAutoCommit(boolean autoCommit):关闭自动提交,打开事物。
-
void commit():提交事务
-
Statement:用于执行sql语句的工具接口。该对象可用于执行DDL、DCL、DML语句,还可用于执行SQL查询。当执行查询时,返回查询到的结果集。常用方法如下:
- ResultSet executeQuery(String sql) throws SQLExcetpion:该方法用于执行查询语句,并返回查询对应的ResultSet对象。只能用于执行查询语句。
- int executeUpdate(String sql) throws SQLExcetpion:用于执行DML语句,并返回受影响的行数。执行DDL语句将返回0。
- boolean execute(String sql) throws SQLExcetpion:该方法可执行SQL语句,如果执行后的第一个结果为ResultSet 对象,则返回True;如果执行后第一个结果为受影响的行数或者没有任何结果,则返回false。
-
PreparedStatement:预编译的Statement 对象。Statement 的子接口,它允许数据库预编译SQL语句(这些SQL语句通常带有参数),疑惑只改变SQL命令的参数,避免了数据库每次都要编译SQL语句,性能更好。相对于Statement 而言,其执行SQL语句时,无须再传入SQL语句,只要为预编译的SQL语句传入参数即可。所以它比Statement 多了如下方法:
- void setXxx(int pramaeterIndex,Xxx value):该方法根据传入参数值的类型不同,需要使用不同的方法。传入的值根据索引传给SQL语句中指定位置的参数。
-
ResultSet:结果集对象。该对象包含查询结果的方法,ResultSet可以通过列索引或列名获得列数据。包含了如下常用方法来移动记录指针:
- void close(): 释放ResultSet() 对象
- boolean absolute(int row):将结果集的指针移动到地row 行,如果row 行是负数,则移动到倒数第 row 行。如果移动后的记录指针指向一条有效记录,则该方法返回true。
- void beforeFirst():将ResultSet指针定位到首行。如果移动后的记录指针指向一条有效的记录,则该方法返回true。
- boolean previous():将ResultSet 的记录指针定位到上一行。如果移动后的之怎记录指向一条有效记录,则该方法返回Ture。
- boolean next():将ResultSet指针的记录定位到下一行,如果移动后的之怎记录指向一条有效记录,则该方法返回Ture。
- boolean last():将ResultSet指针的记录定位到最后一行,如果移动后的之怎记录指向一条有效记录,则该方法返回Ture。
- void afterLast():将ResultSet的记录指针定位到最后一行之后。
JDBC编程步骤
//加载驱动
Class.format(driverClass);
//加载MYSQL驱动
Class.format("com.mysql.jdbc.Driver");
//加载Oracle驱动
Class.format("oracle.jdbc.driver.OracleDriver");
//通过DriverManager获取数据库连接,三个参数:url,用户名,密码
DriverManager.getConnection(String url,String user,String pass);
数据库的URL写法如下:
jdbc:subprotocol:other stuff
// jdbc:固定写法
// subprotocol:指定连接到特定数据库的驱动
// other stuff:不固定,没有较强的规律
// MYSQL数据库URL写法如下:
jdbc:mysql://hostname:port/databasename
// Oracle数据库URL写法如下:
jdbc:oracle:thin:@hostname:port:databasename
通过Connection 对象创建Statement 对象,方法有三种:
- createStatement():创建基本的Statement 对象。
- prepareStatement(String sql):根据传入的SQL语句创建预编译的Statement 对象。
- prepareCall(String call):根据传入的SQL语句创建CallableStatement 对象。
使用Statement执行SQL语句,有如下三个方法:
- excute():可以执行SQL语句,但是比较麻烦。
- excuteUpdate():主要用于执行DML和DDL语句。执行DML语句返回受SQL语句影响的行数,执行DDL语句返回0;
- excuteQuery():只能执行查询语句,执行后返回代表查询结果的ResultSet 对象。
操作结果集
在使用JDBC时需要先导入jar包,导入jar包链接:点击进入
示例:JDBC编程,并通过ResultSet 获得结果集:
// ConnMysql.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class ConnMysql {
public static void main(String[] args) throws ClassNotFoundException {
// TODO Auto-generated method stub
// 1.加载驱动,使用反射知识
Class.forName("com.mysql.cj.jdbc.Driver");
try {
// 2.使用 DriverManager 获取数据库连接
// 其中返回的Connection 就代表了java 程序和数据库的连接
// 不同数据库的URL写法需要查驱动文档,用户名、妈妈有DBA分配
Connection conn =
DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test"+"?serverTimezone=GMT%2B8", "root", "1230");
// 3.使用Connection 创建一个Statement 对象
Statement stmt = conn.createStatement();
// 执行SQL语句
/*
Statement 有三种执行SQL语句的方法:
1.<u>excute</u>():可执行任何SQL语句,返回一个boolean值,第一个结果是ResultSet,则返回true
2.excuteQuery() 执行select 语句,返回查询的结果集.
3.excuteUpdate()用于执行DML语句,返回一个整数
代表被SQL语句影响的记录条数
*/
ResultSet rs = stmt.executeQuery("select * from people");
// ResultSet有一系列的getXxx(列索引|列名)方法,用于记录指针
// 指向行、特定列的值,不断的使用next() 将记录指针下移一行
// 如果移动之后记录指针仍然有效行,则next()返回true
while(rs.next()) {
System.out.println(rs.getInt(1)+"\t"+
rs.getString(2)+"\t"+rs.getString(3));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
执行SQL语句的方式
注:java8新增了 executeLargeUpdate 方法(MYSQL驱动暂时不支持)。
示例:使用executeUpdate()方法创建数据表。
该示例没有直接把数据库连接信息卸载写在程序里,而是使用了一个mysql.ini文件(一个properties文件)来保存数据库连接信息,这是比较成熟的做法。当把程序从开发环境一直到生产环境时,无需修改源码,只需要修改mysql.ini配置文件即可。
// ExecuteDDL.java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class ExecuteDDL {
private String driver;
private String url;
private String user;
private String pass;
public void initParam(String paramFile) throws FileNotFoundException,
IOException {
// 使用properties 类来加载属性文件
Properties props = new Properties();
props.load(new FileInputStream(paramFile));
driver = props.getProperty("driver");
url = props.getProperty("url");
user = props.getProperty("user");
pass = props.getProperty("pass");
}
public void createTable(String sql) throws ClassNotFoundException {
// 加载驱动
Class.forName(driver);
try {
// 获得数据库连接
Connection conn =
DriverManager.getConnection(url,user,pass);
// 使用Connection 来创建一个Statement 对象
Statement stmt = conn.createStatement();
// 执行DDL语句,创建数据表
stmt.executeUpdate(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) throws FileNotFoundException,
IOException, ClassNotFoundException {
ExecuteDDL ed = new ExecuteDDL();
ed.initParam("mysql.ini");
ed.createTable("create table jdbc_test("
+ "jdbc_id int auto_increment primary key,"
+ "jdbc_name varchar(20));");
System.out.println("----建表成功----");
}
}
注:executeUpdate()同样可用于执行DML语句,区别在于DDL返回0,DML返回受影响的记录条数。
使用execute 方法执行SQL语句
execute()方法:几乎可以执行任何SQL语句,但是较麻烦。返回值为boolean,它表明执行该SQL语句是否返回了ResultSet对象。
如何获取执行SQL语句后得到的ResultSet对象呢?
Statement 提供了两个方法来获取结果:
- getResultSet():获取该Statement 执行查询语句所返回的ResultSet对象。
- getUpdateCount():获取该Statement() 执行DML 语句所影响的记录行数。
示例 :略
使用PreparedStatement 执行SQL语句
如果经常需要反复执行一条结构相似的SQL语句,则可以使用PreparedStatement 接口。并且同样提供了execute()、executepdate()、executrQuery()三个方法。不过不需要参数,因为已存储了预编译SQL语句。
// 创建一个PrepareStatement 对象
PrepareStatement pstmt = conn.prepareStatement("inset into people values(?,?,19)");
示例:对比 略(有空写)
示例:以一个简单的登录窗口为例 介绍 略(有空写)
管理结果集
略
Rowset 1.1
略
事务处理
略
分析数据库信息
略
使用连接池管理连接
手动连接数据库的弊端:
数据库连接的建立及关闭是及其消耗系统资源的操作,在多层结构的应用环境中,这种资源的消耗对系统的性能影响尤为明显。通过DriverManager获得的数据库连接,一个数据库对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完后立即关闭连接。频繁的打开、关闭连接将造成系统性能低下。
解决方案
使用数据库连接池,当程序启动时,系统主动建立足够的数据库连接,并将这些连接组成一个连接池。每次应用程序请求数据库连接时,无须重新打开连接,而是从连接池中获取已有的连接使用,使用完后不再关闭数据库连接,而是直接将连接归还给连接池,通过使用连接池,将大大提高程序的运行效率。
数据库连接池是Connection 对象的工厂。数据库连接池的常用参数如下:
- 数据库的初始连接数
- 连接池的最大连接数
- 连接池的最小连接数
- 连接池每次增加的容量
JDBC 的数据库连接池使用java.sql.DataSourse 来表示,DataSourse 只是一个接口,该接口通常由商用服务器(如 WebLogic、WebSphere)等提供实现,也有一些开源组织实现(如DBCP和C3P0)
DBCP数据源
略(本人主要学习的是C3P0(性能更胜一筹))。
C3P0数据源
C3P0:可以自动清理不再使用的Connection,还可以自动清理Statement 和 ResultSet。
下载地址:点击进入下载
下载后得到一个zip文件,解压文件,即可得到JAR文件。
时间问题:有空再搞这个C3P0配置及使用方法。在这先附上一个别人写的链接:点击进入。。。