JDBC详细全解(示例超多)

article/2025/8/24 8:07:32

文章目录

  • JDBC
    • JDBC的概念
        • 1.jdbc的概念
        • 2.jdbc的本质
    • JDBC快速入门
    • JDBC功能详解
      • 1、DriverManager驱动管理对象
      • 2、Connection数据库连接对象
      • 3、Statement执行sql语句的对象
      • 4、ResultSet结果集对象
    • JDBC案例
      • 案例需求
      • 数据准备
        • 1、数据库数据准备
        • 2、创建student类
      • 功能实现
        • 1、查询所有学生信息
        • 2、通过ID查询学生信息
        • 3、添加学生记录
        • 4、修改学生信息
        • 5、删除学生记录
      • 推荐使用工具类
    • SQL注入攻击
    • JDBC事务管理
      • JDBC如何管理事务
    • 数据库连接池
      • 自定义数据库连接池
        • 准备:
        • 示例:
        • 使用测试:
      • 归还连接
        • 归还连接-继承方式
        • 归还连接-装饰设计模式
        • 归还连接-适配器设计模式
    • 动态代理
      • 示例:
      • 动态代理归还数据库连接:
        • 实现重写MyDataSource中的getConnection方法(使用动态代理方式实现)
        • 使用上文中测试代码:
    • 开源数据库连接池
      • C3P0数据库连接池
        • 下载jar包:
        • 导入jar包:
        • 导入配置文件到src目录:
        • 使用示例:
      • Druid数据库连接池
        • 下载jar包:
        • 导入jar包:
        • 编写配置文件:
        • 示例代码:
        • 基于Druid数据库连接池创建的工具类

JDBC

JDBC的概念

1.jdbc的概念

JDBC ( Java DataBaseConnectivity java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问,它是由一组用Java语言编写的类和接口组成的。

2.jdbc的本质

其实就是java官方提供的一套规范(接口)。用于帮助开发人员快速实现不同关系型数据库的连接!

JDBC快速入门

jdbc的快速入门步骤:

1.导入jar包

2.注册驱动

3.获取数据库连接

4.获取执行者对象

5.执行sql语句并返回结果

6.处理结果

7.释放资源

示例代码:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;public class JDBC_index1 {public static void main(String[] args) throws Exception {//注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//MySQL5以后可直接省略//获取数据库连接Connection con= DriverManager.getConnection("jdbc:mysql://localhost:3306/cadastre","root","XXXXXX");//获取执行者对象Statement stat=con.createStatement();//执行sql语句并返回结果String sql="select * from 网易云热评";ResultSet re=stat.executeQuery(sql);//处理结果while (re.next()){System.out.println(re.getString("userId")+"\t"+re.getString("nickname")+"\t"+re.getString("content"));}//释放资源con.close();}
}

JDBC功能详解

1、DriverManager驱动管理对象

(1)注册驱动:(mysql5以后可直接省略驱动)
1.注册给定的驱动程序: staticvoid registerDriver(Driver driver);

2.写代码使用:Class.forName(“com.mysql.jdbc.Driver”);

3.在com.mysql.jdbc.Driver类中存在静态代码块

(2)获取数据库连接:
1.获取数据库连接对象: static ConnectiongetConnection(Stringurl, String user,String password);

2.返回值:Connection数据库连接对象

3.参数
url:指定连接的路径。语法: jdbc:mysql://ip地址(域名):端口号/数据库名称

​ user:用户名

​ password:密码

2、Connection数据库连接对象

1.获取执行者对象:
获取普通执行者对象: Statement createStatement0;
获取预编译执行者对象:PreparedStatement prepareStatement(String sql);

2.管理事务
开启事务 : setAutoCommit(boolean autoCommit);参数为false,则开启事务

​ 提交事务:commit();

​ 回滚事务: rollback();

3.释放资源
立即将数据库连接对象释放:void close();

3、Statement执行sql语句的对象

(1)执行DML语句: int executeUpdate(String sql);

返回值int :返回影响的行数。

参数sql:可以执行insert、update、delete语句。

(2) 执行DQL语句:ResultSet executeQuery(String sql);

返回值ResultSet:封装查询的结果。

参数sql:可以执行select语句。

(3)释放资源
立即将数据库连接对象释放:void close();

4、ResultSet结果集对象

1.判断结果集中是否还有数据: boolean next();

有数据返回true,并将索引向下移动一行。没有数据返回false。

2.获取结果集中的数据:XXX getXxx(“列名”);XXX代表数据类型(要获取某列数据,这一列的数据类型)。

例如: String getString(“name”);int getInt(" age");

3.释放资源

立即将结果集对象释放:void close();

JDBC案例

案例需求

使用JDBC完成对student表的CRUD操作

数据准备

1、数据库数据准备

-- 创建数据库
create DATABASE db14;-- 使用数据库
use db14-- 创建student表
CREATE TABLE student
(id int PRIMARY KEY,sname VARCHAR(20),age int,brithday date
);-- 添加数据
INSERT into student VALUES(1,'张飞',23,'1999-08-11'),(2,'李四',23,'1998-08-11'),(3,'王五',23,'1997-08-11'),(4,'关羽',23,'1995-08-11');

2、创建student类

package Com.Stuclass;import java.util.Date;public class Student {private Integer id;private String sname;private Integer age;private Date birthday;public Student(Integer id, String sname, Integer age, Date birthday) {this.id = id;this.sname = sname;this.age = age;this.birthday = birthday;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getSname() {return sname;}public void setSname(String sname) {this.sname = sname;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "Student{" +"id=" + id +", sname='" + sname + '\'' +", age=" + age +", birthday=" + birthday +'}';}
}

功能实现

1、查询所有学生信息

public ArrayList<Student> findAll() {ArrayList<Student> list=new ArrayList<>();Connection con=null;try {con= DriverManager.getConnection(conName,name,password);Statement statement = con.createStatement();String sql="select * from student";ResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()){Integer id=resultSet.getInt("id");String sname=resultSet.getString("sname");Integer age=resultSet.getInt("age");Date birthday=resultSet.getDate("brithday");Student s=new Student(id,sname,age,birthday);list.add(s);}} catch (SQLException e) {e.printStackTrace();}finally {try {con.close();} catch (SQLException e) {e.printStackTrace();}}return list;}

2、通过ID查询学生信息

public Student findById(Integer id) {Connection con=null;Student s = null;try{con=DriverManager.getConnection(conName,name,password);String sql="select * from student where id=?";PreparedStatement pstate = con.prepareStatement(sql);pstate.setInt(1,id);ResultSet resultSet = pstate.executeQuery();while (resultSet.next()){s=new Student(id,resultSet.getString("sname"),resultSet.getInt("age"),resultSet.getDate("brithday"));}} catch (SQLException e) {e.printStackTrace();}finally {try {con.close();} catch (SQLException e) {e.printStackTrace();}}return s;}

3、添加学生记录

public int insert(Integer id, String sname, Integer age, String  birthday) {Connection con=null;int re=0;Date date=new Date();//需要new一个Date对象SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //设置日期格式  yyyy-MM-dd-HH-mm-ss这个是完整的try {date = dateFormat.parse(birthday);} catch (ParseException e) {e.printStackTrace();}try {con= JDBCUtils.getConnect();String sql="insert into student values(?,?,?,?)";PreparedStatement p=con.prepareStatement(sql);p.setInt(1,id);p.setString(2,sname);p.setInt(3,age);p.setDate(4, new java.sql.Date(date.getTime()));re = p.executeUpdate();} catch (SQLException e) {e.printStackTrace();}finally {try {con.close();} catch (SQLException e) {e.printStackTrace();}}return re;}

4、修改学生信息

 public int update(String name1,Integer age) {Connection con=null;int result=0;String sql="update student " +"set age=? " +"where sname=?";try {con= JDBCUtils.getConnect();PreparedStatement p = con.prepareStatement(sql);p.setInt(1,age);p.setString(2,name1);result = p.executeUpdate();} catch (SQLException e) {e.printStackTrace();}finally {try {con.close();} catch (SQLException e) {e.printStackTrace();}}return result;}

5、删除学生记录

public int delete(Integer id) {Connection con=null;int result=0;try {con= JDBCUtils.getConnect();String sql="delete from student where id=?";PreparedStatement p = con.prepareStatement(sql);p.setInt(1,id);result = p.executeUpdate();} catch (SQLException e) {e.printStackTrace();}finally {try {con.close();} catch (SQLException e) {e.printStackTrace();}}return result;}

推荐使用工具类

配置信息:(在src目录下创建config.properties文件)

driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db14
username=root
password=XXXXXXx

工具类:

package Com.Stuclass.utils;import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;/*
* JDBC工具类
* */
public class JDBCUtils {
//    1、构造方法私有private JDBCUtils(){}
//    2、声明所需要的配置变量private static String driverClass;private static String url;private static String username;private static String password;private static Connection con;//    3、提供静态代码块,读取配置文件信息为变量赋值,注册驱动static {try {
//            赋值InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");Properties pro=new Properties();pro.load(is);driverClass=pro.getProperty("driverClass");url=pro.getProperty("url");username=pro.getProperty("username");password=pro.getProperty("password");
//            注册驱动Class.forName(driverClass);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}
}//        获取数据库连接public static Connection getConnect(){try {con= DriverManager.getConnection(url,username,password);} catch (SQLException e) {e.printStackTrace();}return con;}
//    关闭连接public static void close(Connection con, Statement state, ResultSet rs){if (con!=null){try {con.close();} catch (SQLException e) {e.printStackTrace();}}if (state!=null){try {state.close();} catch (SQLException e) {e.printStackTrace();}}if (rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}}public static void close(Connection con, Statement state){if (con!=null){try {con.close();} catch (SQLException e) {e.printStackTrace();}}if (state!=null){try {state.close();} catch (SQLException e) {e.printStackTrace();}}}
}

SQL注入攻击

利用SQL语句漏洞对系统进行攻击

例如:

按照正常道理来说,我们在密码处输入的所有内容,都应该认为是密码的组成

但是现在Statement对象在执行sql语句时,将密码的一部分内容当做查询条件来执行了

解决方式:

利用预编译SQL语句

JDBC事务管理

JDBC如何管理事务

管理事务的功能类:Connection

​ 开启事务: setAutoCommit(boolean autoCommit);参数为false,则开启事务。

​ 提交事务:commit();

​ 回滚事务:rollback();

数据库连接池

1.数据库连接的背景
数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出对数据库连接的管理能显著影响到整个应用程序的性能指标,数据库连接池正是针对这个问题提出来的

⒉.数据库连接池
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。这项技术能明显提高对数据库操作的性能

自定义数据库连接池

1.DataSource接口概述
javax.sql.DataSource接口∶数据源(数据库连接池)。

Java官方提供的数据库连接池规范(接口)如果想完成数据库连接池技术,就必须实现DataSource接口

核心功能:获取数据库连接对象:Connection getConnection();

2.自定义数据库连接池

定义一个类,实现DataSource接口。

定义一个容器,用于保存多个Connection连接对象。

定义静态代码块,通过JDBC工具类获取10个连接保存到容器中。

重写getConnection方法,从容器中获取一个连接并返回。

定义getSize方法,用于获取容器的大小并返回。

准备:

上文中的JDBCutill工具类和相关配置文件

示例:

package JDBCplus.Demo1;
/*
* 自定义数据库连接池
* */
import JDBCplus.JDBCUtils;import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;public class MyDataSource implements DataSource {
//    1、准备容器  注意必须是线程安全的private static List<Connection> pool= Collections.synchronizedList(new ArrayList<>());
//    2、通过工具类获取10个连接对象static {for (int i = 0; i < 10; i++) {Connection con= JDBCUtils.getConnect();pool.add(con);}
}
//    3、重写getConnection方法@Overridepublic Connection getConnection() throws SQLException {if (pool.size()>0){return pool.remove(0);}else {throw new RuntimeException("连接池已空");}}
//    4、定义getSize方法获取连接池大小public int getSize(){return pool.size();}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}
}

使用测试:

package JDBCplus.Demo1;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class Test {public static void main(String[] args) throws SQLException {MyDataSource myDataSource = new MyDataSource();Connection con=myDataSource.getConnection();String sql="select * from student";Statement statement = con.createStatement();ResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()){System.out.println(resultSet.getInt("id")+" "+resultSet.getString("sname"));}resultSet.close();statement.close();con.close();}
}

image-20221013150926078

归还连接

归还数据库连接的方式:

继承方式

装饰设计模式

适配器设计模式

动态代理方式

归还连接-继承方式

1.继承方式归还数据库连接的思想。

通过打印连接对象,发现DriverManager获取的连接实现类是JDBC4Connection那我们就可以自定义一个类,继承JDBC4Connection这个类,重写close()方法完成连接对象的归还。

2.继承方式归还数据库连接的实现步骤。

1定义一个类,继承JDBC4Connection。

2定义Connection连接对象和连接池容器对象的成员变量。

3通过有参构造方法完成对成员变量的赋值。

4重写close方法,将连接对象添加到池中。

3.继承方式归还数据库连接存在的问题。

通过查看JDBC工具类获取连接的方法发现∶我们虽然自定义了一个子类,完成了归还连接的操作。但是DriverManager获取的还是JDBC4Connection这个对象,并不是我们的子类对象,而我们又不能整体去修改驱动包中类的功能,所继承这种方式行不通!心

(此处我的MySQL包中未找到JDBC4Connection类不能展示)

归还连接-装饰设计模式

1.装饰设计模式归还数据库连接的思想。

我们可以自定义一个类,实现Connection接口。

这样就具备了和JDBC4Connection相同的行为了重写close()方法,完成连接的归还。其余的功能还调用mysql驱动包实现类原有的方法即可。

2.装饰设计模式归还数据库连接的实现步骤。

1、定义一个类,实现Connection接口

2、定义Connection连接对象和连接池容器对象的成员变量

3、通过有参构造方法完成对成员变量的赋值

4、重写close()方法,将连接对象添加到池中

5、剩余方法,只需要调用mysql驱动包的连接对象完成即可

6、在自定义连接池中,将获取的连接对象通过自定义连接对象进行包装

3.装饰设计模式归还数据库连接存在的问题。

实现Connection接口后,有大量的方法需要在自定义类中进行重写

示例代码:

package JDBCplus.Demo2;import java.sql.*;
import java.util.*;
import java.util.concurrent.Executor;public class MyConnection2 implements Connection {
//    定义连接对象和连接池对象private Connection con;private List<Connection> pool;//    构造方法赋值public MyConnection2(Connection con,List<Connection> pool){this.con=con;this.pool=pool;}
//     重写close方法@Overridepublic void close() throws SQLException {pool.add(con);}@Overridepublic Statement createStatement() throws SQLException {return con.createStatement();}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return con.prepareStatement(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return con.prepareCall(sql);}@Overridepublic String nativeSQL(String sql) throws SQLException {return con.nativeSQL(sql);}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {con.setAutoCommit(false);}@Overridepublic boolean getAutoCommit() throws SQLException {return con.getAutoCommit();}@Overridepublic void commit() throws SQLException {con.commit();}@Overridepublic void rollback() throws SQLException {con.rollback();}@Overridepublic boolean isClosed() throws SQLException {return con.isClosed();}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {return con.getMetaData();}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {con.setReadOnly(false);}@Overridepublic boolean isReadOnly() throws SQLException {return con.isReadOnly();}@Overridepublic void setCatalog(String catalog) throws SQLException {con.setCatalog(catalog);}@Overridepublic String getCatalog() throws SQLException {return con.getCatalog();}@Overridepublic void setTransactionIsolation(int level) throws SQLException {con.setTransactionIsolation(level);}@Overridepublic int getTransactionIsolation() throws SQLException {return con.getTransactionIsolation();}@Overridepublic SQLWarning getWarnings() throws SQLException {return con.getWarnings();}@Overridepublic void clearWarnings() throws SQLException {con.clearWarnings();}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {return con.createStatement(resultSetType,resultSetConcurrency);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareStatement(sql,resultSetType,resultSetConcurrency);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareCall(sql,resultSetType,resultSetConcurrency);}@Overridepublic Map<String, Class<?>> getTypeMap() throws SQLException {return con.getTypeMap();}@Overridepublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {con.setTypeMap(map);}@Overridepublic void setHoldability(int holdability) throws SQLException {con.setHoldability(holdability);}@Overridepublic int getHoldability() throws SQLException {return con.getHoldability();}@Overridepublic Savepoint setSavepoint() throws SQLException {return con.setSavepoint();}@Overridepublic Savepoint setSavepoint(String name) throws SQLException {return con.setSavepoint(name);}@Overridepublic void rollback(Savepoint savepoint) throws SQLException {con.rollback();}@Overridepublic void releaseSavepoint(Savepoint savepoint) throws SQLException {con.releaseSavepoint(savepoint);}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareStatement(sql,resultSetType,resultSetConcurrency);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {return con.prepareStatement(sql,autoGeneratedKeys);}@Overridepublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {return con.prepareStatement(sql,columnIndexes);}@Overridepublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {return con.prepareStatement(sql,columnNames);}@Overridepublic Clob createClob() throws SQLException {return con.createClob();}@Overridepublic Blob createBlob() throws SQLException {return con.createBlob();}@Overridepublic NClob createNClob() throws SQLException {return con.createNClob();}@Overridepublic SQLXML createSQLXML() throws SQLException {return con.createSQLXML();}@Overridepublic boolean isValid(int timeout) throws SQLException {return con.isValid(timeout);}@Overridepublic void setClientInfo(String name, String value) throws SQLClientInfoException {con.setClientInfo(name,value);}@Overridepublic void setClientInfo(Properties properties) throws SQLClientInfoException {con.setClientInfo(properties);}@Overridepublic String getClientInfo(String name) throws SQLException {return con.getClientInfo(name);}@Overridepublic Properties getClientInfo() throws SQLException {return con.getClientInfo();}@Overridepublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {return con.createArrayOf(typeName,elements);}@Overridepublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {return con.createStruct(typeName,attributes);}@Overridepublic void setSchema(String schema) throws SQLException {con.setSchema(schema);}@Overridepublic String getSchema() throws SQLException {return con.getSchema();}@Overridepublic void abort(Executor executor) throws SQLException {con.abort(executor);}@Overridepublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {con.setNetworkTimeout(executor,milliseconds);}@Overridepublic int getNetworkTimeout() throws SQLException {return con.getNetworkTimeout();}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return con.unwrap(iface);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return con.isWrapperFor(iface);}
}

更改MyDataSouce(数据库连接池方法):

//    3、重写getConnection方法@Overridepublic Connection getConnection() throws SQLException {if (pool.size()>0){Connection con = pool.remove(0);MyConnection2 myCon=new MyConnection2(con,pool);return myCon;}else {throw new RuntimeException("连接池已空");}}

测试代码:

package JDBCplus.Demo1;import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;public class Test {public static void main(String[] args) throws SQLException {MyDataSource myDataSource = new MyDataSource();System.out.println(myDataSource.getSize());Connection con=myDataSource.getConnection();System.out.println(myDataSource.getSize());System.out.println(con.getClass());String sql="select * from student";Statement statement = con.createStatement();ResultSet resultSet = statement.executeQuery(sql);while (resultSet.next()){System.out.println(resultSet.getInt("id")+" "+resultSet.getString("sname"));}resultSet.close();statement.close();con.close();System.out.println(myDataSource.getSize());}
}
image-20221013164305855

发现父类为自定义类,使用后连接池大小为10

归还连接-适配器设计模式

1.适配器设计模式归还数据库连接的思想。

我们可以提供一个适配器类,实现Connection接口,将所有方法进行实现(除了close方法

自定义连接类只需要继承这个适配器类,重写需要改进的close方法即可

2.适配器设计模式归还数据库连接的实现步骤。

1定义一个适配器类,实现Connection接口。

2定义Connection连接对象的成员变量。

3通过有参构造方法完成对成员变量的赋值。

4重写所有方法(除了close ),调用mysq驱动包的连接对象完成即可。

5定义一个连接类,继承适配器类。

6定义Connection连接对象和连接池容器对象的成员变量,并通过有参构造进行赋值。

7重写close()方法,完成归还连接。

8在自定义连接池中,将获取的连接对象通过自定义连接对象进行包装。

3.适配器设计模式归还数据库连接存在的问题。

自定义连接类虽然很简洁了,但适配器类还是我们自己编写的,也比较的麻烦

示例代码:

适配器类:(重写除close外的所有方法,抽象类)

package JDBCplus.Dome3;import java.sql.*;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;/*
* 适配器类
* */
public abstract class MyAdapter implements Connection{private Connection con;public MyAdapter(Connection con){this.con=con;}@Overridepublic Statement createStatement() throws SQLException {return con.createStatement();}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return con.prepareStatement(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return con.prepareCall(sql);}@Overridepublic String nativeSQL(String sql) throws SQLException {return con.nativeSQL(sql);}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {con.setAutoCommit(false);}@Overridepublic boolean getAutoCommit() throws SQLException {return con.getAutoCommit();}@Overridepublic void commit() throws SQLException {con.commit();}@Overridepublic void rollback() throws SQLException {con.rollback();}@Overridepublic boolean isClosed() throws SQLException {return con.isClosed();}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {return con.getMetaData();}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {con.setReadOnly(false);}@Overridepublic boolean isReadOnly() throws SQLException {return con.isReadOnly();}@Overridepublic void setCatalog(String catalog) throws SQLException {con.setCatalog(catalog);}@Overridepublic String getCatalog() throws SQLException {return con.getCatalog();}@Overridepublic void setTransactionIsolation(int level) throws SQLException {con.setTransactionIsolation(level);}@Overridepublic int getTransactionIsolation() throws SQLException {return con.getTransactionIsolation();}@Overridepublic SQLWarning getWarnings() throws SQLException {return con.getWarnings();}@Overridepublic void clearWarnings() throws SQLException {con.clearWarnings();}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {return con.createStatement(resultSetType,resultSetConcurrency);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareStatement(sql,resultSetType,resultSetConcurrency);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {return con.prepareCall(sql,resultSetType,resultSetConcurrency);}@Overridepublic Map<String, Class<?>> getTypeMap() throws SQLException {return con.getTypeMap();}@Overridepublic void setTypeMap(Map<String, Class<?>> map) throws SQLException {con.setTypeMap(map);}@Overridepublic void setHoldability(int holdability) throws SQLException {con.setHoldability(holdability);}@Overridepublic int getHoldability() throws SQLException {return con.getHoldability();}@Overridepublic Savepoint setSavepoint() throws SQLException {return con.setSavepoint();}@Overridepublic Savepoint setSavepoint(String name) throws SQLException {return con.setSavepoint(name);}@Overridepublic void rollback(Savepoint savepoint) throws SQLException {con.rollback();}@Overridepublic void releaseSavepoint(Savepoint savepoint) throws SQLException {con.releaseSavepoint(savepoint);}@Overridepublic Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareStatement(sql,resultSetType,resultSetConcurrency);}@Overridepublic CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {return con.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability);}@Overridepublic PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {return con.prepareStatement(sql,autoGeneratedKeys);}@Overridepublic PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {return con.prepareStatement(sql,columnIndexes);}@Overridepublic PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {return con.prepareStatement(sql,columnNames);}@Overridepublic Clob createClob() throws SQLException {return con.createClob();}@Overridepublic Blob createBlob() throws SQLException {return con.createBlob();}@Overridepublic NClob createNClob() throws SQLException {return con.createNClob();}@Overridepublic SQLXML createSQLXML() throws SQLException {return con.createSQLXML();}@Overridepublic boolean isValid(int timeout) throws SQLException {return con.isValid(timeout);}@Overridepublic void setClientInfo(String name, String value) throws SQLClientInfoException {con.setClientInfo(name,value);}@Overridepublic void setClientInfo(Properties properties) throws SQLClientInfoException {con.setClientInfo(properties);}@Overridepublic String getClientInfo(String name) throws SQLException {return con.getClientInfo(name);}@Overridepublic Properties getClientInfo() throws SQLException {return con.getClientInfo();}@Overridepublic Array createArrayOf(String typeName, Object[] elements) throws SQLException {return con.createArrayOf(typeName,elements);}@Overridepublic Struct createStruct(String typeName, Object[] attributes) throws SQLException {return con.createStruct(typeName,attributes);}@Overridepublic void setSchema(String schema) throws SQLException {con.setSchema(schema);}@Overridepublic String getSchema() throws SQLException {return con.getSchema();}@Overridepublic void abort(Executor executor) throws SQLException {con.abort(executor);}@Overridepublic void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {con.setNetworkTimeout(executor,milliseconds);}@Overridepublic int getNetworkTimeout() throws SQLException {return con.getNetworkTimeout();}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return con.unwrap(iface);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return con.isWrapperFor(iface);}
}

自定义连接类:

package JDBCplus.Dome3;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/*
* 自定义连接类
* */
public class MyConnection3 extends MyAdapter {//    定义连接对象和连接池对象private Connection con;private List<Connection> pool;//    构造方法赋值public MyConnection3(Connection con,List<Connection> pool) {super(con);this.con=con;this.pool=pool;}@Overridepublic void close() throws SQLException {pool.add(con);}
}

数据库连接池更改:

//    3、重写getConnection方法@Overridepublic Connection getConnection() throws SQLException {if (pool.size()>0){Connection con = pool.remove(0);MyConnection3 myCon=new MyConnection3(con,pool);return myCon;}else {throw new RuntimeException("连接池已空");}}

测试代码:

(同装饰设计模式)

image-20221013170409082

目标到达

动态代理

动态代理:

在不改变目标对象方法的情况下对方法进行增强

组成:

被代理对象︰真实的对象

代理对象︰内存中的一个对象

要求:

代理对象必须和被代理对象实现相同的接口

示例:

student类:

package proxy;public class Student implements StudentInterface{@Overridepublic void eat(String name){System.out.println("学生吃"+name);}@Overridepublic void study(){System.out.println("在家自学");}
}

StudentInterface接口:

package proxy;public interface StudentInterface {public void eat(String name);public void study();
}

测试:

package proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {Student student = new Student();student.study();student.eat("米饭");/** 要求不改动Student的代码,更改study方法的输出内容* *///参数一:类加载器,参数二:接口类型class数组,参数三:代理规则StudentInterface proxy= (StudentInterface) Proxy.newProxyInstance(student.getClass().getClassLoader(), new Class[]{StudentInterface.class}, new InvocationHandler() {/** 执行student类中所有的方法都会经过invoke方法* 对method方法判断,修改想要的方法* */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(method.getName().equals("study")){System.out.println("不去学习");return null;}else {return method.invoke(student,args);}}});proxy.eat("米饭");proxy.study();}
}

运行结果:

image-20221013173931028

成功修改

动态代理归还数据库连接:

1.动态代理方式归还数据库连接的思想。

我们可以通过Proxy来完成对Connection实现类对象的代理

代理过程中判断如果执行的是close方法,就将连接归还池中。

如果是其他方法则调用连接对象原来的功能即可

2.动态代理方式归还数据库连接的实现步骤。

定义一个类,实现DataSource接口

定义一个容器,用于保存多个Connection连接对象

定义静态代码块,通过JDBC工具类获取10个连接保存到容器中

重写getConnection方法,从容器中获取一个连接

通过 Proxy代理,如果是close方法,就将连接归还池中。如果是其他方法却则调用原有功能

定义getSize方法,用于获取容器的大小并返回

实现重写MyDataSource中的getConnection方法(使用动态代理方式实现)

//   3、重写getConnection方法   使用动态代理方式实现@Overridepublic Connection getConnection() throws SQLException {if (pool.size()>0){Connection con = pool.remove(0);Connection myCon = (Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), new Class[]{Connection.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("close")){pool.add(con);return null;}else {return method.invoke(con,args);}}});return myCon;}else {throw new RuntimeException("连接池已空");}}

使用上文中测试代码:

image-20221014160000515

开源数据库连接池

C3P0数据库连接池

1.C3PO数据库连接池的使用步骤。

导入jar包。

导入配置文件到src目录下。

创建C3PO连接池对象。

获取数据库连接进行使用。

注意:C3PO的配置文件会自动加载,但是必须叫c3p0-config.xml或 c3pO-config.properties

下载jar包:

官网:https://sourceforge.net/projects/c3p0/files/latest/download

别人百度网盘:百度网盘下载链接:https://pan.baidu.com/s/1o9cBkMVb_kZmAksZjjoZYg 密码:c7pr

导入jar包:

image-20221014163706222

导入配置文件到src目录:

image-20221014163828508

使用示例:

package C3P0;import com.mchange.v2.c3p0.ComboPooledDataSource;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class Test1 {public static void main(String[] args) throws SQLException {
//        1、创建c3p0数据库连接池ComboPooledDataSource dataSource = new ComboPooledDataSource();
//        2、通过连接池获取数据库连接Connection con = dataSource.getConnection();
//        3、执行数据库操作String sql="select * from student";PreparedStatement p = con.prepareStatement(sql);ResultSet re = p.executeQuery();while (re.next()){System.out.println(re.getInt("id")+"\t"+re.getString("sname"));}}
}
image-20221014163917795

Druid数据库连接池

1、介绍

Druid(德鲁伊)是阿里巴巴开发的号称为监控而生的数据库连接池,Druid是目前最好的数据库连接池。在功能、性能、扩展性方面,都超过其他数据库连接池,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

1.Druid数据库连接池的使用步骤:

导入jar包。

编写配置文件,放在src目录下。

通过Properties集合加载配置文件。

通过Druid连接池工厂类获取数据库连接池对象。

获取数据库连接进行使用。

注意:Druid不会自动加载配置文件,需要我们手动加载,但是文件的名称可以自定义。

下载jar包:

别人的百度网盘::https://pan.baidu.com/s/1U9v5c_DindqXva92JeRVJQ 密码:nquq

导入jar包:

image-20221014171619816

编写配置文件:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db14
username=root
password=xxxxxx
initialSize=5
maxActive=10
maxWait=3000

示例代码:

package Druid;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;public class test1 {public static void main(String[] args) throws Exception {
//        获取配置文件的流对象InputStream is = test1.class.getClassLoader().getResourceAsStream("druid.properties");
//        通过properties集合,加载配置文件Properties properties = new Properties();properties.load(is);
//        通过Druid连接池工厂类获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//        连接池中获取连接对象Connection con = dataSource.getConnection();
//        执行数据库操作String sql="select * from student";PreparedStatement p = con.prepareStatement(sql);ResultSet re = p.executeQuery();while (re.next()){System.out.println(re.getInt("id")+"\t"+re.getString("sname"));}}
}
image-20221014174345716

基于Druid数据库连接池创建的工具类

代码:

package Druid;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;public class DruidUtils {
//    私有化构造方法private DruidUtils(){}
//    声明数据源变量private static DataSource dataSource;
//    静态代码块完成配置文件加载和获取数据库连接对象static {InputStream is = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");Properties properties = new Properties();try {properties.load(is);dataSource = DruidDataSourceFactory.createDataSource(properties);}catch (Exception e) {e.printStackTrace();}
}
//   获取数据库连接public static Connection getConnection(){Connection con=null;try {con = dataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return con;}
//   获取数据库连接池public static DataSource getDataSource(){return dataSource;}//    关闭连接public static void close(Connection con, Statement state, ResultSet rs){if (con!=null){try {con.close();} catch (SQLException e) {e.printStackTrace();}}if (state!=null){try {state.close();} catch (SQLException e) {e.printStackTrace();}}if (rs!=null){try {rs.close();} catch (SQLException e) {e.printStackTrace();}}}public static void close(Connection con, Statement state){if (con!=null){try {con.close();} catch (SQLException e) {e.printStackTrace();}}if (state!=null){try {state.close();} catch (SQLException e) {e.printStackTrace();}}}
}

使用示例:

package Druid;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class test2 {public static void main(String[] args) throws SQLException {Connection con=DruidUtils.getConnection();String sql="select * from student";PreparedStatement p = con.prepareStatement(sql);ResultSet re = p.executeQuery();while (re.next()){System.out.println(re.getInt("id")+"\t"+re.getString("sname"));}}
}
image-20221014180438643

http://chatgpt.dhexx.cn/article/0rAGilia.shtml

相关文章

JDBC介绍

1 JDBC简介 概念&#xff1a;JDBC(Java DataBase Connectivity) &#xff1a;Java数据库连接技术&#xff1a;具体讲就是通过Java连接广泛的数据库&#xff0c;并对表中数据执行增、删、改、查等操作的技术。如图所示&#xff1a; 此前我们学习过SQL后&#xff0c;可以通过 Na…

JDBC 连接 MySQL

哈喽~大家好&#xff0c;这次我们来看看 JDBC 如何 连接 MySQL. 目录 一、开头 二、介绍 1、JDBC 的概念 2、JDBC 的功能 3、JDBC 的常用接口和类 三、数据库的创建&#xff08;MySQL&#xff09; 1、连接 MySQL (1)、注册驱动 (2)、获取连接 (3)、获取执行者连接 …

BindingNavigator 类 - MSDN

.NET Framework 2.0 其他版本 5&#xff08;共 9&#xff09;对本文的评价是有帮助 - 评价此主题 注意&#xff1a;此类在 .NET Framework 2.0 版中是新增的。 表示窗体上绑定到数据的控件的导航和操作用户界面 (UI)。 命名空间:System.Windows.Forms 程序集:System.Windows.Fo…

Android的一个BindView工具的实现

对于Android已经有很多Bind View的工具了&#xff0c;大多都是使用了反射和注解的方法。那么如何实现一个简易的代码生成工具呢&#xff1f;其实不难&#xff0c;只要会写代码都可以试试。这些天&#xff0c;我试了一下&#xff0c;并将它做成了工具。代码如下&#xff1a; pa…

setNavigationBarTitle

wx.setNavigationBarTitle就是用来改红框框里面的内容滴 在项目开发中经常用到 使用的场景就包括了多个地方用同一套页面的时候 wx.setNavigationBarTitle({title: "我的店铺",});

安卓ViewBinding详解

背景 之前我们通过Kotlin Android Extensions来访问布局文件中的元素&#xff0c;但是这个现在被废弃了&#xff0c;原因如下&#xff1a; 空安全&#xff1a;res下的任何id都可以被访问&#xff0c;有可能因访问了非当前Layout下的id而出错兼容性&#xff1a;只能在kotlin中…

Winform中用bindingNavigator和bingdingSource实现分页

BindingNavigator控件介绍 可以使用BindingNavigator控件来创建标准化的方法&#xff0c;以便用户搜索和更改 Windows 窗体上的数据。BindingNavigator 控件由包含一系列 ToolStripItem 对象的ToolStrip组成&#xff0c;可以实现&#xff1a;添加数据&#xff0c;删除数据&…

DataGridView使用bindingNavigator实现分页功能(应用存储过程)

想法是这样的&#xff1a;使用bindingNavigator存储过程实现DataGridView的分页功能&#xff0c;其中包含简单的查询。 存储过程如下&#xff1a; --创建分页查询存储过程(含输出参数&#xff0c;输入参数&#xff08;含搜索功能&#xff09;) use HotelDB if exists(select *…

配置bind

安装bind yum install bind-* service firewalld stop #暂时关闭防火墙 vim /etc/named.conf Linsten-on port 53 {any;}; 监听除了自己以外的ip Allow-query{any&#xff1b;} 允许任意的ip来访问 配置正向解析 /etc/named.rfc1912.zones #直接在底部添加 zone "s…

Android dataBinding和viewBinding的混淆配置

在最近重构过的项目中有使用dataBinding或viewBinding&#xff0c;在调试的时候没有问题&#xff0c;但是在混淆过后出现了崩溃&#xff1a; 我们知道viewbinding的初始化是ActivityMainBinding.inflate() 而我是通过反射去初始化viewbinding的 很明显&#xff0c;布局所生成的…

viewBinding和@BindView的用法的简单使用

viewBinding 1.module下的build.gradle&#xff0c;在闭包android{ }里面添加 viewBinding {enabled true} 2.使用方法 用视图绑定功能后&#xff0c;系统会为该模块中包含的每个 XML 布局文件生成一个绑定类。这个类的类名是以xml布局文件名去掉下换线后&#xff0c;单词…

BindingNavigator控件

WinForm之中BindingNavigator控件的使用 在微软WinForm中&#xff0c;BindingNavigator控件主要用来绑定数据。可以将一个数据集合与该控件绑定&#xff0c;以进行数据 联动的显示效果。如图下图所示&#xff1a; 那么&#xff0c;下面我们就来用BindingNavigator控件做一下上图…

WinForm控件之【BindingNavigator】【DataSet】【BindingSource】【DataGridView】

基本介绍 数据类控件&#xff0c;数据加载绑定便捷应用相当广泛&#xff0c;具体看例子自行扩展吧&#xff1b; 常设置属性 BindingNavigator--BindingSource&#xff1a;数据来源&#xff0c;绑定后默认项会根据相应的操作按钮执行操作&#xff1b; BindingNavigator--Items&a…

WinForm之中BindingNavigator控件的使用

在微软WinForm中&#xff0c;BindingNavigator控件主要用来绑定数据。可以将一个数据集合与该控件绑定&#xff0c;以进行数据联动的显示效果。如图下图所示&#xff1a; 那么&#xff0c;下面我们就来用BindingNavigator控件做一下上图所示的效果。 分析&#xff1a;该案例以B…

winform控件之BindingNavigator

BindingNavigator控件可以为我们绑定的数据提供一个导航的功能&#xff0c;默认的工具是这个样子的&#xff0c;我们可以根据需求再增加功能 1.BindingNavigator用法 1.1界面布局 界面布局如下 一个BindingNavigator名为bindingNavigator1 一个DataGridView名为DataGridVie…

C#开发之——ToolStrip(10.22)

一 概述 在C# WinForm开发中添加工具栏(ToolStrip)和添加菜单栏类似&#xff0c;在工具箱中将ToolStrip控件直接拖到Windows窗体中即可 <!--more--> 二 ToolStrip操作 从工具箱拖拽ToolStrip控件到Windows窗体后&#xff0c;如下图所示(在添加了ToolStrip控件之后&…

C#winform窗体控件之toolStrip

C#winform窗体控件之toolStrip 在做窗体时我们可能需要一个工具栏&#xff0c;那这时最简单的方法就是添加一个toolStrip控件。 如何完成一个上图的工具栏呢? 首先&#xff0c;需要添加一个toolStrip控件&#xff0c;然后点击控件上的添加按钮&#xff0c;添加你需要的控件&…

C#如何让ToolStrip工具栏按钮分别靠左和靠右对齐分布

ToolStrip工具栏按钮默认靠左对齐&#xff0c;如何让ToolStrip工具栏按钮分别靠左和靠右对齐分布&#xff1f;&#xff01; 第一步&#xff0c;选择要靠右对齐的工具栏上的按钮&#xff0c;属性&#xff0c;设置“Alignment: Right” 即&#xff0c;this.toolStripSysInfoBut…

ToolStrip

&#xfeff;&#xfeff; 效果实现&#xff1a; 1.添加ToolStrip控件 2.点击ToolStrip控件添加button,设置Imagine,对ToolStripButton的Text进行设置,DisplayStyle设置为ImagineAndText即可。

ToolStrip控件中如何添加功能按钮

1&#xff0c;在工具箱中选择ToolStrip控件 2&#xff0c;在属性框&#xff0c;选择item 3,进入该界面&#xff0c;选择添加类型 4&#xff0c;指定选定控件的类型 name:控件的名字&#xff0c;相当于对象名。 text&#xff1a;指定控件中内容限制字段 image&#xff1a;指…