文章目录

  • 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();}
}

归还连接

归还数据库连接的方式:

继承方式

装饰设计模式

适配器设计模式

动态代理方式

归还连接-继承方式

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());}
}

发现父类为自定义类,使用后连接池大小为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("连接池已空");}}

测试代码:

(同装饰设计模式)

目标到达

动态代理

动态代理:

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

组成:

被代理对象︰真实的对象

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

要求:

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

示例:

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();}
}

运行结果:

成功修改

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

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("连接池已空");}}

使用上文中测试代码:

开源数据库连接池

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包:

导入配置文件到src目录:

使用示例:

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"));}}
}

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包:

编写配置文件:

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"));}}
}

基于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"));}}
}

JDBC详细全解(示例超多)相关推荐

  1. html+css+js适合前端小白的实战全解(超详细)——2048小游戏(三)

    续上一小节,我们回到newgame()这个函数,我们之前只做了init()内函数,相当于一个初始化操作 现在,我们需要再随机两个两个生成数字. 随机生成数字在这个游戏里会经常出现,用户移动一步,也会产 ...

  2. html+css+js适合前端小白的实战全解(超详细)——2048小游戏(二)

    续上一小节,我们可以发现每一个grid-cell上的数字初始时并不在格子里. 这些数字可以随着玩家的操作而移动 ​ 我们可以想象:初始时每一个格子上的数为0,他们并不显示 ↓ 只有当grid-cell ...

  3. 纯干货分享:CCD图像传感器知识全解,超详细!

    纯干货分享:CCD图像传感器知识全解,超详细! 今天给大家介绍CCD图像传感器,关注我们的朋友会很明显的知道,鼎易鸿基&万酷电子在介绍产品扫描枪的时候会有这样一句话"采用工业级高性能 ...

  4. 2022win11系统 MySQL下载安装配置全解(超详细哟)

    本文手把手教你如何下载.安装以及配置MySQL,配有详细的文字解说以及丰富的过程步骤图解,在安装和配置的过程中可能会出现的问题,以及对应问题的解决方案都有详细说明,希望对大家有所帮助,记得点个赞哟! ...

  5. Android Bitmap史上最详细全解 | 原力计划

    作者 | ༺ IF ༻ 责编 | 王晓曼 出品 | CSDN博客 Bitmap的相关使用 关于 Bitmap ,之前以为它和 Drawable 差不多,就是一种图片,直到泪水打湿了我胸前的红领巾,我决 ...

  6. java垃圾回收算法超详细全解

    目录 一.开始 垃圾标记阶段:对象存活判断 垃圾清除阶段 二.垃圾标记阶段算法--引用计数法 循环引用 证明java未使用引用计数算法 小结 三.垃圾标记阶段算法--可达性分析算法(根搜索算法.追踪性 ...

  7. suid提权全解(超细)

    SUID (Set owner User ID up on execution) 是给予文件的一个特殊类型的文件权限.在 Linux/Unix中,当一个程序运行的时候, 程序将从登录用户处继承权限.S ...

  8. r library car_基础方法 | 用R语言完成量化论文全流程示例!附超详细R脚本

    基础方法 ♪ Method R语言的优点 对于有一定数据分析基础的朋友们来说,要入门R语言并不是十分困难的.但是这毕竟是一门专业性很强的技术,我们当然希望投入精力掌握R语言之后能够得到相应的回报. 在 ...

  9. ESP-01S开发环境搭建及新手教程点灯教程全解详细配图(ESP8266-01s)

    ESP-01S开发环境搭建及新手教程点灯教程全解相当详细(ESP8266-01s) 一.模组简介 二.开发工具 三.开发软件 四.点亮第一盏灯 五.至此完成了ESP-01S在arduino开发环境下点 ...

最新文章

  1. 最萌算法学习来啦,看不懂才怪!| 码书
  2. Oracle NVL()和NVL2()函数
  3. 花神的数论题(这题...哎。数位dp咋就这么 not naive 呢)
  4. ras私钥c#转java_C#RSA对接JAVA中RSA方式代码实例
  5. Dependence Injection
  6. oracle insert into values select from,ORACLE语法中的INSERT INTO。。。SELECT。。。 收藏
  7. 201521123023《Java程序设计》第13周学习总结
  8. java 学习书籍 转载
  9. 极简风格的响应式简历模板
  10. vue+node+mongodb实现的功能
  11. 聚焦设计交易与商业落地 DANG·DHUB设计师平台上线【图】_品牌资讯_服饰_太平洋时尚网...
  12. 《maven的学习》 尚硅谷Maven视频(maven零基础入门)B站
  13. 下载网络图片并上传微信公众平台素材库
  14. 【C#】 .NET Reflector 安装与学习
  15. Linux 文件系统类型 文件系统结构 与Windows文件系统的比较
  16. 10以内加减法编程_500字以内的面向对象编程。
  17. TCP/IP -- 物理层
  18. 回环接口(loopback)
  19. 无法勾选远程连接到计算机,客户端无法连接到远程计算机错误的解决方法
  20. js作为websocket client,服务用java 点对点、一对多聊天

热门文章

  1. CSM与PMI-ACP的对比
  2. 基于Python的图像分类 项目实践——图像分类项目的指导文档
  3. 【Android签名文件META-INF】
  4. `Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig`
  5. 部品se分析_5Why分析(完整版).ppt
  6. 《全球互联网金融商业模式:格局与发展》——第2章,第2节在线折扣券商
  7. 浙江大学计算机学院 英语竞赛 陈星,喜报 | 浙大代表队获得CCPC中国大学生程序设计竞赛冠军...
  8. OleDbDataAdapter 的Update语句执行时提示“insert into语法错误”解决方法
  9. Python tkinter 从入门到放弃(窗口函数)
  10. 鸡蛋壳发软怎么治疗 增强鸡蛋壳质量的特效药