详解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的实现与优化(万字详解)的主要内容,如果未能解决你的问题,请参考以下文章

万字长文详解HiveSQL执行计划

万字长文详解HiveSQL执行计划

万字长文详解HiveSQL执行计划

万字长文详解HiveSQL执行计划

DBA整理的万字详解MySQL性能优化,值得收藏!

DBA整理的万字详解MySQL性能优化,值得收藏!