里面的数据库连接池所需要的jar包可以在这里面下载:

https://blog.csdn.net/m0_49647974/article/details/115287069

文章目录

  • 一.概念:Java DataBase Connectivity
  • 二.具体流程:
  • 三. 代码实现
  • 四.详解各个对象:
    • 1.DriverManager :驱动管理对象
      • (1)注册驱动:
      • (2)获取数据库连接:
    • 2.Connection :数据库连接对象
      • (1)获取执行中的sql对象
      • (2)管理事务
    • 3.Statement :执行sql的对象
    • 4.Resultset :结果集对象
    • 5.Preparedstatement :执行sql的对象
  • 五、数据库连接池
    • 1.标准接口:DataSourcejavax.sql包下的
    • 2.数据库厂商实现:
    • 3.C3P0:数据库连接池技术
    • 4.Druid:数据库连接池实现技术(阿里巴巴)
  • 六.Spring JDBC
  • 记录:学习中遇到的一些bug
    • 1.JDBC连接时错误:closing inbound before receiving peer's close_notify
    • 2.JDBC连接时错误:
    • 3.C3P0数据库连接池报错:An attempt by a client to checkout a Connection has timed out.
    • 4.警告: Cannot resolve com.mysq.jdbc.Connection.ping method. Will use 'SELECT 1' instead.

一.概念:Java DataBase Connectivity

Java 数据库连接,Java语言操作数据库

JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

二.具体流程:

(1)导入驱动jar包 如:mysql-connector-java-5.1.37-bin.jar

  1. 复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
  2. 右键–>Add As Library

(2)注册驱动

(3)获取数据库连接对象connection4.

(4)定义sql

(5)获取执行sql语句的对象statement6.

(6)执行sq1,接受返回结

(7)处理结果

(8)释放资源

三. 代码实现

/*** @Auther: Parsifal* @Date: 2021/03/22/20:04* @Description:*/
public class JDBCTest {public static void main(String[] args) {Connection connection = null;Statement statement = null;try {//1、导入驱动jar包//2、注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//3、获取数据库连接对象String userName = "root";String password = "root";//报错一:The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to util// 解决方法与原因:当mysql和connector版本八以上时,系统时区错误,需要在配置连接数据库的url加上:?serverTimezone=GMT%2B8// 报错二: javax.net.ssl.SSLException: closing inbound before receiving peer's close_notify//解决方法:需要在配置连接数据库的url加上: &useSSL=falseconnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false", userName, password);//4、定义sql语句String sql = "SELECT * FROM student";//5、获取执行sql的对象、Statementstatement = connection.createStatement();boolean execute = statement.execute(sql);//6、处理结果System.out.println(execute);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {//7、关闭资源if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}
}

但是我们一般都会把这些代码封装成一个Util,把数据库信息写在配置文件里面,如下:

/*** @Auther: Parsifal* @Date: 2021/03/24/21:24* @Description:*/
public class JDBCUtil {private static String url;private static String user;private static String password;private static String driver;//静态模块会在类加载时执行static {FileInputStream fileInputStream = null;try {//properties处理属性文件//获取src路径下的文件的方式一(stream)Properties properties = new Properties();fileInputStream = new FileInputStream("jdbc.properties");//加载流对应的文件properties.load(fileInputStream);//获取src路径下的文件的方式二(path)
/*            ClassLoader classLoader = JDBCUtil.class.getClassLoader();URL resource = classLoader.getResource("jdbc.properties");String path = resource.getPath();  //获取绝对路径System.out.println(path);properties.load(new FileReader(path));*/url = properties.getProperty("url");user = properties.getProperty("user");password = properties.getProperty("password");driver = properties.getProperty("driver");Class.forName(driver);} catch (IOException | ClassNotFoundException e) {e.printStackTrace();} finally {if (fileInputStream!=null){try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}}}public static Connection getConnection(){try {return DriverManager.getConnection(url,user,password);} catch (SQLException throwables) {throwables.printStackTrace();}return null;}//关闭资源public static void close(Statement statement, Connection connection, ResultSet resultSet){if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}if (resultSet!=null){try {resultSet.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}
}//关闭资源 重载方法public static void close(Statement statement, Connection connection){if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}
}

jdbc.properties配置文件

url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false
user=root
password=root
driver=com.mysql.cj.jdbc.Driver

四.详解各个对象:

1.DriverManager :驱动管理对象

(1)注册驱动:

​ static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。

​ 写代码使用: class.forName(“com.mysql.jdbc.Driver”); 把此类加载进内存。

(注意:在mysql5之后的驱动jar包可以省略注册驱动的步骤)

​ 在com.mysql.jdbc.Driver类中存在以下静态代码块,在类加载时运行创建Driver类。

static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}
}

(2)获取数据库连接:

方法:DriverManager.getConnection(“jdbc:mysql://localhost:3306/test”, userName, password);

参数

  • url:指定连接路径 : jdbc:mysql:// ip地址(域名): 端口 /数据库名称

  • 用 " ?"在url后边可以添加属性,”&”可以连接不同的属性,以下举例一些属性:

    ​ serverTimezone=GMT mysql8版本以上要加上,作用为调整时区

    ​ allowMultiQueries=true,支持mybatis执行多条语句;

    ​ useSSL=false,是否进行ssl连接,高版本可能需要设为true;

    ​ serverTimezone=UTC,设置时区

  • uersName:用户名称,password:密码。

  • 注意如果是本机mysql服务器,并且mysql服务默认端口为3306,则url可以不写(jdbc:mysql:///test)

2.Connection :数据库连接对象

(1)获取执行中的sql对象

  • Statement createStatement() 创建Statement对象
  • PreparedStatement preparedStatement(String sql)

(2)管理事务

事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败

为什么要使用事务?

首先我们先了解没有事务的时候:如果不通过事务方式管理SQL语句。此时的SQL语句的提交(commit),是由驱动程序负责管理,在SQL执行完后,就会自动帮我们进行提交,每一条SQL都相当于一个事务。但是执行多条相关联SQL语句,而不通过事务来管理时。如果再某些步骤中中止或操作失误,就会破坏数据库的一致性。(如下,由于没有通过事务sql,我有两条sql语句修改两个内容,当第一条语句执行完后,中间遇到步骤终止和操作失误,会导致第二条sql无法执行。这是很严重的后果。)
步骤:

  • 开启事务: setAutocommit(boolean autocommit):调用该方法设置参数为false,即开启事务
  • 提交事务: commit()
  • 回滚事务: rollback()
 //JDBC事务@Testpublic void test2(){Connection connection = null;Statement statement = null;PreparedStatement preparedStatement1 =null;PreparedStatement preparedStatement2 =null;try {//获取连接connection = JDBCUtil.getConnection();//开启事务connection.setAutoCommit(false);//修改id=1的学生的绩点String sql1 = " update student set name='张三'  where id= ? ";//修改id=2的学生的绩点String sql2 = "update student set name='李四'  where id= ? ";preparedStatement1 = connection.prepareStatement(sql1);preparedStatement2 = connection.prepareStatement(sql2);preparedStatement1.setInt(1,1);preparedStatement2.setInt(1,2);preparedStatement1.executeUpdate();//手动制造异常
//            int a =1/0;preparedStatement2.executeUpdate();//提交事务connection.commit();} catch (Exception throwables) {try {//事务的回滚if (connection!=null) {connection.rollback();}} catch (SQLException e) {e.printStackTrace();}throwables.printStackTrace();} finally {JDBCUtil.close(preparedStatement1, connection);if (preparedStatement2!=null) {try {preparedStatement2.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}}

没有使用事务(两条语句中间手动制造异常,第一条语句执行)


使用事务同时无法执行(两条语句都无法执行)

3.Statement :执行sql的对象

  • 执行sql语句

    • boolean execute(string sql):可以执行任意的sql
    • int executeUpdate(string sql)∶执行DML (insert、update、delete)语句、DDL(对表和库的操作如:create,alter,drop)语句
      • 该方法的返回值是影响的行数、如果返回值>0则执行成功,反之,则失败
    • Resultset executeQuery(string sql)︰执行DQL (select)语句

4.Resultset :结果集对象

  • 常用方法:

    • boolean next():游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
    • getxxx(参数):获取数据xxx:代表数据类型如: int getInt() , string getstring()
      1. int : 代表列的编号,从1开始如:getstring(1)
      2. String :代表列名称。如: getDouble(“email”)
      3. 如图:getString(1)与getDouble(“id”)是同一个值

5.Preparedstatement :执行sql的对象

作用: 预编译sql语句防止恶意sql注入

  1. SQL注入问题∶在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题

    • 输入用户随便,输入密码:a’ or "a’ = 'a
    • sql : select * from user where username = 'fhdsjkf’ and password = ‘a’ or ‘a’ = ‘a’
  2. 使用方法:

    (1)使用 ?占位符写sql(如 :select * from student where id = ?and grade=?)

    (2)获取执行sql语句的对象Preparedstatement Connection.prepareStatement(String sql)

    (3)给?赋值:格式preparedstatement.setXxx(参数1,参数2) ==>参数1:?的位置,参数2:?的值

    (4)执行sql,接受返回结果,不需要传递sql语句

@Test
public void test1(){Connection connection = null;PreparedStatement preparedStatement =null;try {connection = JDBCUtil.getConnection();//使用 ?占位符写sqlString sql = "select * from  student where id = ? and  grade=? ";//给?赋值preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1,1);preparedStatement.setFloat(2,3.5f);ResultSet resultSet = preparedStatement.executeQuery();//处理结果while (resultSet.next()) {int id = resultSet.getInt("id");String name = resultSet.getString("name");String email = resultSet.getString("email");double grade = resultSet.getDouble("grade");System.out.println(id + name + email + grade); //结果:1 zzz 564894525@qq.com 3.5}} catch (SQLException throwables) {throwables.printStackTrace();} finally {JDBCUtil.close(preparedStatement, connection);}}

五、数据库连接池

概念::其实就足一个容器(集合),存放数据库连接的容器。当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

好处:

  • 节约资源
  • 用户访问高效

实现:

1.标准接口:DataSourcejavax.sql包下的

  • 方法∶

    • 获取连接:getConnection()
    • 归还连接:connection.close()。如果连接对貌Connection是从连接池中获取的,那么调用connection.close()方法,则不会再关闭连接了。而是归还连接

2.数据库厂商实现:

  • C3P0:数据库连接池技术
  • Druid:数据库连接池实现技术(阿里巴巴)

3.C3P0:数据库连接池技术

  1. 导入jar两个 c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar
  2. 定义配置文件:
    • 名称:c3p0.properties 或者 c3p0-config.xml (注意:C3P0只能识别这两个配置文件)
    • 路径:直接接将文件放在src目录下即可。
  3. 创建核心对象数据库连接池对象comboPooledDataSource
  4. 获取连接: getConnection
/*** @Auther: Parsifal* @Date: 2021/03/27/20:38* @Description:  C3P0的演示*/
public class C3P0Test {public static void main(String[] args) throws SQLException {//        1、创建数据库连接池对象 ->使用默认配置
//        DataSource ds = new ComboPooledDataSource();//使用指定配置DataSource ds = new ComboPooledDataSource("otherc3p0");
//        2、获取连接对象Connection conn = ds.getConnection();System.out.println(conn);conn.close();}
<?xml version="1.0" encoding="utf-8"?>
<c3p0-config>
<!--  使用默认的配置读取连接池对象--><default-config>
<!--    连接参数--><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&amp;useSSL=false</property><property name="user">root</property><property name="password">root</property>
<!--    连接池参数-->
<!--    初始化申请的连接数量--><!-- 初始化五个Connection对象--><property name="initialPoolSize">5</property>
<!--  最大连接数量--><property name="maxPoolSize">10</property>
<!--    如果申请不到,最多会等待三秒--><property name="checkoutTimeout">3000</property></default-config><named-config name="otherc3p0"> </named-config>
</c3p0-config>

4.Druid:数据库连接池实现技术(阿里巴巴)

  1. 导人jar包druid-1.o.9.jar定义配置i文件:

    • 可以叫任何名称,可以放在任何目录下
    • 是properties形式的
  2. 获取数据库连接池对象∶通过工厂来来获取DruidDataSourceFactory
  3. 获取连接∶getConnection

实现代码:

package DateSource;import DateSource.Druid.DruidTest;
import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;/*** @Auther: Parsifal* @Date: 2021/03/27/22:22* @Description:  使用Druid数据库连接池的JDBCUtil*/
public class JDBCUtil {static DataSource ds;static {//加载配置文件try {//1、导入jar包//2、定义配置文件//3、加载配置文件  不可以默认配置文件 ,必须指定文件Properties  properties =new Properties();InputStream is = DruidTest.class.getClassLoader().getResourceAsStream("druid.properties");properties.load(is);//4、获取数据库连接池对象ds = DruidDataSourceFactory.createDataSource(properties);} catch (Exception e) {e.printStackTrace();}}/*** 获取连接* @return* @throws SQLException*/public static Connection getConnection() throws SQLException {return ds.getConnection();}/*** 关闭资源* @param resultSet* @param statement* @param connection*/public static void close(ResultSet resultSet, Statement statement, Connection connection){if (resultSet!=null){try {resultSet.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (statement!=null){try {statement.close();} catch (SQLException throwables) {throwables.printStackTrace();}}if (connection!=null){try {connection.close();} catch (SQLException throwables) {throwables.printStackTrace();}}}/*** 重载* @param statement* @param connection*/public static void close(Statement statement ,Connection connection){close(null,statement,connection);}/*** 获取数据库连接池* @return*/public static DataSource getDataSource(){return ds;}
}

六.Spring JDBC

spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发步骤︰

步骤:

  1. 导入四个jar包 spring-tx-5.0.5.RELEASE.jar spring-jdbc-5.0.5.RELEASE.jar spring-core-5.0.5.RELEASE.jar spring-beans-5.0.5.RELEASE.jar commons-logging-1.2.jar

  2. 创建JdbcTemplate对象。依赖于数据源Datasource

  3. 调用JdbcTemplate的方法来完成CRUD的操作

    • update():执行DML语句。增、删、改语句

    • queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value将这条记录封装为一个map集合

      • 注意:这个方法查询的结果集长度只能是1
    • queryForList():查询结果将结果集封装为list集合

      • 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
    • query():查询结果,将结果封装为javaBean对象

      • 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
    • query的参数:RowMapper

      • 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装new
      • BeanPropertyRowMapper<类型>(类型.class)
    • queryForobject :查询结果,将结果封装为对象

/*** @Auther: Parsifal* @Date: 2021/03/28/14:12* @Description:*/
public class JDBCTemplateTest {//1、导入jar//2、创建JDBCTemplate对象static   JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtil.getDataSource());//查询所有的记录用List集合@Testpublic void test(){String sql = "select * from student";//自定义接口List<Student> students = jdbcTemplate.query(sql, new RowMapper<Student>() {@Overridepublic Student mapRow(ResultSet resultSet, int i) throws SQLException {int id = resultSet.getInt("id");String name = resultSet.getString("name");String email = resultSet.getString("email");float grade = resultSet.getFloat("grade");Student student = new Student(id,name,email,grade);return student;}});students.forEach(System.out::println);}//查询所有的记录用List集合@Testpublic void test1(){String sql = "select * from student";//使用封装好的接口List<Student> students = jdbcTemplate.query(sql,new BeanPropertyRowMapper<Student>(Student.class));students.forEach(System.out::println);}
}

记录:学习中遇到的一些bug

mysql版本号为8.0.13

1.JDBC连接时错误:closing inbound before receiving peer’s close_notify

解决方法与原因:配置连接数据库的url错误,在后面加上&useSSL=false即可

2.JDBC连接时错误:

The server time zone value ‘Öйú±ê׼ʱ¼ä’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you want to util


解决方法与原因:当mysql和connector版本八以上时,系统时区错误,需要在配置连接数据库的url加上:?serverTimezone=GMT%2B8

3.C3P0数据库连接池报错:An attempt by a client to checkout a Connection has timed out.

解决方法与原因:配置文件的url错误(并且注意:&需要转义为&)

<property name="jdbcUrl">jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&amp;useSSL=false</property>

顺便说一下:可以试试看其他的解决方法:

  • 重启mysql服务

  • <property name="checkoutTimeout">3000</property>  改大等待时间
    
  • <property name="maxPoolSize">10</property> 改小最大连接数量
    

4.警告: Cannot resolve com.mysq.jdbc.Connection.ping method. Will use ‘SELECT 1’ instead.


解决方法与原因:druid版本与mysql版本不兼容,更换druid版本1.1.21即可

2021-3-28 JDBC入门包含数据库连接池相关推荐

  1. Java JDBC篇4——数据库连接池

    Java JDBC篇4--数据库连接池 1.DBCP 1.1.依赖jar包 官网:https://mvnrepository.com/artifact/org.apache.commons/commo ...

  2. JDBC开发之数据库连接池

    JDBC开发之数据库连接池 使用数据库连接池优化程序性能 应用程序直接获取链接的缺点:用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万 ...

  3. JDBC中C3PO数据库连接池详解

    -----------------------------------------------------JDBC中C3PO数据库连接池详解------------------------------ ...

  4. 【JavaWeb】JDBC优化 之 数据库连接池、Spring JDBC

    1 数据库连接池 为什么要使用数据库连接池? 数据库连接是一件费时的操作,连接池可以使多个操作共享一个连接 使用连接池可以提高对数据库连接资源的管理 节约资源且高效 概念:数据库连接池其实就是一个容器 ...

  5. java银行管理系统(MySql+JDBC+数据库(Druid数据库连接池)+GUI)重要代码有解析注释

    java银行管理系统 小白又来水博客了 文章目录 java银行管理系统 一.项目需求与分析: 二.知识及有关技术的概述: 三.银行管理系统需求的具体实现: 四.部分功能预览: 五.Last: 一.项目 ...

  6. JDBC学习笔记03【JDBC事务管理、数据库连接池、JDBCTemplate】

    黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...

  7. JDBC——数据库连接池

    目录 前言 一.为什么要使用数据库连接池 二.数据库连接池 2.1 优点 三.多种开源数据库连接池 3.1 C3P0数据库连接池 3.2 DBCP连接池 3.3 Druid(德鲁伊)数据库连接池 总结 ...

  8. 数据库连接池的选择及其开发配置

    转载自  数据库连接池的选择及其开发配置 一.数据库连接池概述 数据库连接的建立是一种耗时.性能低.代价高的操作,频繁的数据库连接的建立和关闭极大的影响了系统的性能.数据库连接池是系统初始化过程中创建 ...

  9. 数据库驱动和JDBC、DBCP-C3P0连接池

    目录 数据库驱动 第一个JDBC程序 statement对象详解 SQL注入问题 PreparedStatement对象 JDBC操作事务 DBCP-C3P0连接池 DBCP C3P0 C3P0与DB ...

最新文章

  1. OC学习7——类别、扩展和协议
  2. mysql 查看锁_MySQL反应慢的排查思路
  3. 79. 单词搜索(dfs)
  4. 关于JAVA异常处理的20个最佳实践
  5. ReactiveLodeBalancerClientFilter响应式负载均衡代理
  6. javafx窗体程序_JavaFX真实世界应用程序:欧洲电视网广播联盟
  7. Exam化的软件项目管理
  8. echo 多行_Java中Scanner的用法:单行多行输入
  9. leetcode题解102-二叉树的层序遍历
  10. JavaScript学习总结(4)——JavaScript数组
  11. ipad是买WiFi版的好,还是买4G版的好?
  12. 普中28335开发攻略_带你了解TI的DSP入门芯片TMS320F28335
  13. linux 搜索文件后缀名,Linux -find、文件后缀名
  14. 泛泰A870K去掉相机快门声音的方法
  15. java des ecb_DES ECB加解密的Java实现
  16. 论文写作-如何提高英语论文写作水平
  17. 处理火绒弹窗拦截无法开机启动
  18. 读书笔记——高效能人士的七个习惯3
  19. 【Alpha】阶段第九次Scrum Meeting
  20. 架构师修炼系列【FMEA故障分析与影响分析】

热门文章

  1. 大数据挖掘分析工具集
  2. 好家伙,你的 GitHub 年度报告曝光!
  3. oppo watch安装王者荣耀,adb完整代码及步骤
  4. linux python prophet,在python中使用Prophet预测每个类别的值
  5. Python3原生爬虫获取熊猫直播某一分类下的主播人气并保存到Excel
  6. apicloud优化点击事件与tapmode
  7. linux系统调用的来龙去脉(上)
  8. 北京工商大学计算机软件技术基础课件,《智能科学与技术专业发展问题》 课件.ppt...
  9. 笔记本电脑进水后的正确处理方法
  10. android_binder