详解JDBC的实现与优化(万字详解)
Posted 勇敢牛牛不怕困难@帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解JDBC的实现与优化(万字详解)相关的知识,希望对你有一定的参考价值。
JDBC详解
简介
JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库。从根本上来说,JDBC 是一种规范,它提供了一套完整的接口,允许便携式访问到底层数据库,因此可以用 Java 编写不同类型的可执行文件。
执行流程:
连接数据源,如:数据库。
为数据库传递查询和更新指令。
处理数据库响应并返回的结果。
所需的接口和类
1.Connection接口
Connection 对象的数据库能够提供信息描述其表、所支持的 SQL 语法、存储过程和此连接的功能等。默认情况下,Connection 对象处于自动提交模式下,这意味着它在执行每个语句后都会自动提交更改。如果禁用自动提交模式,为了提交更改,必须显式调用 commit 方法;否则无法保存数据库更改。
createStatement()方法:
创建一个 Statement 对象来将 SQL 语句发送到数据库。没有参数的 SQL 语句通常使用 Statement 对象执行。如果多次执行相同的 SQL 语句,使用 PreparedStatement 对象可能更有效。
getMetaData()方法:
获取 DatabaseMetaData 对象,该对象包含关于 Connection 对象连接到的数据库的元数据。元数据包括关于数据库的表、受支持的 SQL 语法、存储过程、此连接的功能等信息。
rollback(Savepoint savepoint) 方法:
取消在当前事务中进行的所有更改,并释放此 Connection 对象当前保存的所有数据库锁定。此方法应该只在已禁用自动提交模式时使用。
setAutoCommit(boolean autoCommit) 方法:
将此连接的自动提交模式设置为给定状态。如果连接处于自动提交模式下,则将执行其所有 SQL 语句,并将这些语句作为单独的事务提交。否则,其 SQL 语句将成组地进入通过调用 commit 方法或 rollback 方法终止的事务中。默认情况下,新的连接处于自动提交模式下。
Savepoint setSavepoint(String name)方法:
添加事务回滚的点,在当前事务中创建一个具有给定名称的保存点,并返回表示它的新 Savepoint 对象。
2. Statement接口
用于执行静态 SQL 语句并返回它所生成结果的对象。
在默认情况下,同一时间每个 Statement 对象在只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与读取另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。
executeUpdate(String sql) 方法:
执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。
executeQuery(String sql) 方法:
执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。
3.ResultSet接口
表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
ResultSet 对象具有指向其当前数据行的指针。最初,指针被置于第一行之前。next 方法将指针移动到下一行;因为该方法在 ResultSet 对象中没有下一行时返回 false,所以可以在 while 循环中使用它来迭代结果集。
默认的 ResultSet 对象不可更新,仅有一个向前移动的指针。因此,只能迭代它一次,并且只能按从第一行到最后一行的顺序进行。可以生成可滚动和/或可更新的 ResultSet 对象。以下代码片段(其中 con 为有效的 Connection 对象)演示了如何生成可滚动且不受其他更新影响的、可更新的结果集。请参阅 ResultSet 字段以了解其他选项。
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
next() 方法:
判断resultset的接受结果,采用循环遍历,查询结果!在知道数据库表里参数类型的情况下,采用resultset的getint方法。
Properties类(父类是hashtable)
Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。
一个属性列表可包含另一个属性列表作为它的“默认值”;如果未能在原有的属性列表中搜索到属性键,则搜索第二个属性列表。
因为 Properties 继承于 Hashtable,所以可对 Properties 对象应用 put 和 putAll 方法。但强烈反对使用这两个方法,因为它们允许调用方插入其键或值不是 Strings 的项。相反,应该使用 setProperty 方法。如果在“有危险”的 Properties 对象(即包含非 String 的键或值)上调用 store 或 save 方法,则该调用将失败。
load 和 store 方法按下面所指定的、简单的面向行的格式加载和存储属性。此格式使用 ISO 8859-1 字符编码。可以使用 Unicode 转义符来编写此编码中无法直接表示的字符;转义序列中只允许单个 ‘u’ 字符。可使用 native2ascii 工具对属性文件和其他字符编码进行相互转换。
getProperty(String key) 方法:
用指定的键在此属性列表中搜索属性。
setProperty(String key, String value) 方法:
调用 Hashtable 的方法 put。
DataSource类
该工厂用于提供到此 DataSource 对象表示的物理数据源的连接。作为 DriverManager 设施的替代项,DataSource 对象是获取连接的首选方法。实现 DataSource 接口的对象通常在基于 JavaTM Naming and Directory Interface (JNDI) API 的命名服务中注册。
DataSource 接口由驱动程序供应商实现。共有三种类型的实现:
1.基本实现 - 生成标准 Connection 对象
2.连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
3.分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,并且几乎始终参与连接池。此实现与中间层事务管理器一起使用,并且几乎始终与连接池管理器一起使用。
DataSource 对象的属性在需要时可以修改。例如,如果将数据源移动到另一个服务器,则可更改与服务器相关的属性。其优点是,因为可以更改数据源的属性,所以任何访问该数据源的代码都无需更改。
通过 DataSource 对象访问的驱动程序不会向 DriverManager 注册。通过查找操作检索 DataSource 对象,然后使用该对象创建 Connection 对象。使用基本的实现,通过 DataSource 对象获取的连接与通过 DriverManager 设施获取的连接相同。
getConnection() 方法:
尝试建立与此 DataSource 对象表示的数据源的连接。
DriverManager类
管理一组 JDBC 驱动程序的基本服务。
注:DataSource 接口是 JDBC 2.0 API 中的新增内容,它提供了连接到数据源的另一种方法。使用 DataSource 对象是连接到数据源的首选方法。
getConnection(String url) 方法:
试图建立到给定数据库 URL 的连接。
PreparedStatement接口(Statement的子接口)
表示预编译的 SQL 语句的对象。
SQL 语句被预编译并且存储在 PreparedStatement 对象中。然后可以使用此对象高效地多次执行该语句。
注:用来设置 IN 参数值的 setter 方法(setShort、setString 等等)必须指定与输入参数的已定义 SQL 类型兼容的类型。例如,如果 IN 参数具有 SQL 类型 INTEGER,那么应该使用 setInt 方法。
如果需要任意参数类型转换,使用 setObject 方法时应该将目标 SQL 类型作为其参数的类型。
在以下设置参数的示例中,con 表示一个活动连接:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
executeQuery() 方法:
在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。
getMetaData() 方法:
检索包含有关 ResultSet 对象的列消息的 ResultSetMetaData 对象,ResultSet 对象将在执行此 PreparedStatement 对象时返回。
基础版的JDBC
作为简单功能的实现,并不是通用的方法每次实现功能单一,没有实现功能统一。
package jdbc;
import java.sql.*;
public class Connect {
public static void main(String [] args) throws Exception{
//Class.forName("com.mysql.cj.jdbc.Driver");
//1.注册jdbc驱动
String driverName="com.mysql.cj.jdbc.Driver";
//2.获取连接对象
String dbURL="jdbc:mysql://127.0.0.1:3306/mytest?useSSL=false&serverTimezone=UTC";
String userName="root";
String userPwd="123456";//数据库密码(自己设置的)
try{
Class.forName(driverName);
System.out.println("加载驱动成功!");
}catch(Exception e){
e.printStackTrace();
System.out.println("加载驱动失败!");
}
try{
Connection dbConn=DriverManager.getConnection(dbURL,userName,userPwd);
System.out.println("连接数据库成功!");
}catch(Exception e){
e.printStackTrace();
System.out.print("MySQL80连接失败!");
}
Connection Conn=DriverManager.getConnection(dbURL,userName,userPwd);
Statement stat=Conn.createStatement();
String sql = "select * from tb1";
ResultSet result = stat.executeQuery(sql);
while(result.next()) {
System.out.print("username:"+result.getString("username")+"|");
System.out.println("age:"+result.getInt("age"));
}
result.close();
stat.close();
Conn.close();
}
}
通用版本的JDBC(采用Statement)
1.JDBCUtils通用抽象类:
package mysql.jdbc;
import fs.反射.ReflectionUtils;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public abstract class JDBCUtils {
private static String url = null;
private static String name =null;
private static String password = null;
private Connection conn= null;
private Statement st = null;
private PreparedStatement ps =null;
private ResultSet rs = null;
private ResultSetMetaData rsm =null;
private static DataSource dataSource =null;
static{
Properties properties = new Properties();
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
try {
properties.load(is);
String driver =properties.getProperty("driverClassName"); url = properties.getProperty("url");
name = properties.getProperty("username");
password = properties.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getconnection() throws SQLException {//获取链接
return DriverManager.getConnection(url,name,password);
}
//---------------statement方法
public boolean update(String sql) {//数据库的修改
int bRet =0;
try {
conn = getconnection();
st = conn.createStatement();
bRet = st.executeUpdate(sql);
//System.out.println(bRet);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return bRet!=0;
}
public static void jdbcClose(Connection conn,Statement st,ResultSet rs) {//jbdc数据库关闭
try {
rs.close();
if(rs!=null){
rs = null;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
st.close();
if(st!=null){
st = null;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
conn.close();
if(conn!=null){
conn = null;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void jdbcClose(Connection conn,Statement st) {
try {
st.close();
if(st!=null){
st = null;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
conn.close();
if(conn!=null){
conn = null;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public boolean delete(String sql) {//删除
int bRet =0;
try {conn = getconnection();
st = conn.createStatement();
bRet = st.executeUpdate(sql);
//System.out.println(bRet);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return bRet!=0;
}
public boolean inster(String sql) throws SQLException {
int i = 0;
try {
conn = getconnection();
st = conn.createStatement();
i = st.executeUpdate(sql);
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return i!=0;
}
//单条 多条
public abstract Object reToObj(ResultSet rs);
public abstract List<Object> rsToList(ResultSet rs);
public Object queryOne(String sql) throws SQLException {
Object obj =null;
conn = getconnection();
st = conn.createStatement();
rs = st.executeQuery(sql);
obj = reToObj(rs);
return obj;
}
public List<Object> queryAll(String sql) throws SQLException {
List<Object> list =null;
conn = getconnection();
st = conn.createStatement();
rs = st.executeQuery(sql);
list = rsToList(rs);
return list;
}
}
2.db.properties文件
方便统一规划,管理驱动、用户、密码、以及数据库表。
driverClassName = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/test1
username = root
password = 123456
3.User类
执行对象
package jdbc;
public class User {
private int id;
private String username;
private String password;
public User() {
// TODO Auto-generated constructor stub
}
public User(int id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public String getUserName() {
return username;
}
public String getPassWord() {
return password;
}
public void setId(int id) {
this.id = id;
}
public void setUsername(String userName) {
this.username = userName;
}
public void setpassword(String passWord) {
this.password = passWord;
}
@Override
public String toString() {
return "id:["+id+"]userName:["+username+"]passWord:["+password+"]";
}
}
4.UserDao类
操作类对接数据库
package jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class UserDao extends JDBCUtils{
User user = new User();
@Override
public Object reToObj(ResultSet rs) {
try {
if(rs.next()) {
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setpassword(rs.getString("password"));
}
} catch (SQLException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return (Object)user;
}
@Override
public List<Object> rsToList(ResultSet rs) {
List<Object> list = new ArrayList<>();
try {
while(rs.next()) {
以上是关于详解JDBC的实现与优化(万字详解)的主要内容,如果未能解决你的问题,请参考以下文章