目录

一、JDBC核心组件

二、使用步骤

三、连接步骤

1.导包

2.注册JDBC驱动程序:

3.数据库URL配置,创建连接对象

(1)加载驱动

(2)获得链接

(3)定义sql,创建状态通道

(4)关闭资源

(5)完整代码

四、SQl注入和预状态通道PreparedStatement

五、多表操作

1.创建bean下的实体

2.创建接口和实现接口

3.在demo中打印查询结果

4.结果

六、事务的应用

1.自动提交/手动提交切换

2.事务的提交commit和回滚rollback

3.保存点Savepoints

七、JDBC批处理

1.Statement批处理

2.PreparedStatement批处理

八、反射处理结果集

九、封装工具类

十、属性文件

十一、连接池

1.DBCP(不可以自动回收空闲连接)

2.C3P0(自动回收空闲连接)

3.Druid德鲁伊(阿里开发)


JDBC是一种用于执行SQL语句的Java API,可以在各种平台上使用Java,如Windows,Mac OS和各种版本的UNIX。

一、JDBC核心组件

DriverManager: 此类管理数据库驱动程序列表。使用通信子协议将来自java应用程序的连接请求 与适当的数据库驱动程序匹配。
Driver:此接口处理与数据库服务器的通信,我们很少会直接与Driver对象进行交互。而是使用 DriverManager对象来管理这种类型的对象。
Connection:该界面具有用于联系数据库的所有方法。连接对象表示通信上下文,即,与数据库 的所有通信仅通过连接对象。
Statement:使用从此接口创建的对象将SQL语句提交到数据库。除了执行存储过程之外,一些派 生接口还接受参数。
ResultSet:在使用Statement对象执行SQL查询后,这些对象保存从数据库检索的数据。它作为一 个迭代器,允许我们移动其数据。
SQLException:此类处理数据库应用程序中发生的任何错误

二、使用步骤

构建JDBC应用程序涉及以下六个步骤:
- 导入包:需要包含包含数据库编程所需的JDBC类的包。大多数情况下,使用import java.sql.*就足够 了。
- 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。
- 打开连接:需要使用DriverManager.getConnection()方法创建一个Connection对象,该对象表 示与数据库的物理连接。
- 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。
- 从结果集中提取数据:需要使用相应的ResultSet.getXXX()方法从结果集中检索数据。
- 释放资源:需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集。

三、连接步骤

1.导包

import java.sql.*

2.注册JDBC驱动程序:

工程下创建lib文件夹,把mysql-connector压缩包放入lib下,点击左上角文件复选框-项目结构,打开此界面,点击依赖

点击+,单击第一个JAR或目录,找到刚刚的lib文件下压缩包,点击确定注入。

3.数据库URL配置,创建连接对象

这是为了创建一个格式正确的地址,指向要连接到的数据库。

(1)加载驱动

 Class.forName("com.mysql.cj.jdbc.Driver");//从本地工程加载驱动

(2)获得链接

创建数据库连接对象

String userName = "root";//数据库用户名
String userPassword = "123456";//数据库密码
String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//数据库mysql8 URL配置
Connection connection = DriverManager.getConnection(url,userName, userPassword);

加载驱动程序后,可以使用DriverManager.getConnection()方法建立连接。
- getConnection(String url)
- getConnection(String url,Properties prop)
- getConnection(String url,String user,String password)

完整的连接地址:
第一种:jdbc:mysql://localhost:3306/yhp2?serverTimezone=UTC
        localhost:数据库地址,本地就是这个 3306:数据库所用的端口 yhp2:要打开的数据库名
第二种:jdbc:mysql://localhost:3306/数据库名?useSSL=false&useUnicode=true&characterEncoding=UTF-8

(3)定义sql,创建状态通道

Statement statement = connection.createStatement();
ResultSet resultSet=statement.executeQuery("select  * from student;");//执行查询while (resultSet.next()) {System.out.println("编号:"+resultSet.getInt("stuid")+"\t姓名" +resultSet.getString("name")+"\t\t生日"+resultSet.getDate("birthday"));
}
执行查询的语句:返回的是一个结果集(executeQuery)
resultSet=statement.executeQuery("select  * from student;");

执行增删改的语句,返回数大于0成功,否则失败。(executeUpdate)
int i=statement.executeUpdate("update student set birthday='1011-1-1' ");

ResultSet:
用resultset接收结果集

(4)关闭资源

resultSet.close();
statement.close();
connection.close();

(5)完整代码

import java.sql.*;public class Demo1 {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String userName = "root";String userPassword = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, userName, userPassword);statement = connection.createStatement();resultSet = statement.executeQuery("select  * from student;");while (resultSet.next()) {System.out.println("编号:" + resultSet.getInt("stuid")+ "\t姓名" + resultSet.getString("name")+ "\t\t生日" + resultSet.getDate("birthday"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
}

四、SQl注入和预状态通道PreparedStatement

现在网站比较安全,但还是要考虑到。sql注入就是在执行sql语句的时候,比如输入密码的时候夹带别的对数据库安全有威胁的sql语句,如密码输入 or 1=1;那样条件恒等,就可以随便进入

预状态通道,PreparedStatement此种方式将sql语句中的输入用?代替,确保sql语句的本块在传到了数据库执行时带有引号如错误密码变成了 ' 123456 or 1=1',因为有了引号就都变成了字符串,or不会再被当成条件执行,之后按照从1开始1的下标顺序以此给?赋值

此代码块和第三模块第(3)定义sql,创建状态通道相通,经过更改后变成下面,换了案例,用用户名和密码为例子

String sql = "select  * from userVIP where userName=? and userPass=?";//问号占位
PreparedStatement preparedStatement = connection.prepareStatement(sql);//PreparedStatement接收数据
preparedStatement.setString(1, "张三");//按照从1开始的下标顺序给sql语句中的问号赋值
preparedStatement.setString(2, "123456");
resultSet = preparedStatement.executeQuery();

解决了sql注入后的完整代码

import java.sql.*;public class Demo1 {public static void main(String[] args) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String userName = "root";String userPassword = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";;connection = DriverManager.getConnection(url, userName, userPassword);String sql = "select  * from userVIP where userName=? and userPass=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, "张三");preparedStatement.setString(2, "123456");resultSet = preparedStatement.executeQuery();while (resultSet.next()) {System.out.println("编号:"+resultSet.getInt("id")+"\t用户名" +resultSet.getString("userName")+"\t\t密码"+resultSet.getString("userPass"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (preparedStatement != null) {preparedStatement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
}

五、多表操作

一对多,多对一,一对一,多对多

记录一个多对多

一个学生可以学很多课程,一个课程也可以有很多学生在学,形成多对多关系。

1.创建bean下的实体

Student

package bean;import java.util.List;public class Student {private int stuid;private String stuname;private int teacherid;private List<Subject> subjects;public int getStuid() {return stuid;}public void setStuid(int stuid) {this.stuid = stuid;}public String getStuname() {return stuname;}public void setStuname(String stuname) {this.stuname = stuname;}public int getTeacherid() {return teacherid;}public void setTeacherid(int teacherid) {this.teacherid = teacherid;}public List<Subject> getSubjects() {return subjects;}public void setSubjects(List<Subject> subjects) {this.subjects = subjects;}
}

Subject

package bean;import java.util.List;public class Subject {private int subid;private String subname;private List<Student> students;public int getSubid() {return subid;}public void setSubid(int subid) {this.subid = subid;}public String getSubname() {return subname;}public void setSubname(String subname) {this.subname = subname;}public List<Student> getStudents() {return students;}public void setStudents(List<Student> students) {this.students = students;}
}

2.创建接口和实现接口

接口功能是根据科目id查找谁在学习本课程,或者根据学生id查找这个学生学习了哪些课程。

interface StudentSubjectDao
package impl;import bean.Student;
import bean.Subject;public interface StudentSubjectDao {Subject getSubjectId(int subid);Student getStudentId(int stuid);
}
StudentSubjectDaoImp
package dao;import bean.Student;
import bean.Subject;
import impl.StudentSubjectDao;import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class StudentSubjectDaoImp implements StudentSubjectDao {@Overridepublic Subject getSubjectId(int subid) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String userName = "root";String userPass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, userName, userPass);String SQL = "select * FROM middle m,student st,subject su where m.stuid=st.stuid and m.subid=su.subid and m.subid=?";preparedStatement = connection.prepareStatement(SQL);preparedStatement.setInt(1, subid);resultSet = preparedStatement.executeQuery();Subject subject = new Subject();List<Student> students = new ArrayList<>();while (resultSet.next()) {subject.setSubid(resultSet.getInt("subid"));subject.setSubname(resultSet.getString("subname"));Student student = new Student();student.setStuname(resultSet.getString("stuname"));student.setStuid(resultSet.getInt("stuid"));students.add(student);}subject.setStudents(students);return subject;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}return null;}@Overridepublic Student getStudentId(int stuid) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String user = "root";String pass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, user, pass);String sql = "select * from middle m,student st,subject su where su.subid=m.subid and st.stuid=m.stuid and m.stuid=?";preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, stuid);resultSet = preparedStatement.executeQuery();Student student = new Student();List<Subject> subjects = new ArrayList<>();while (resultSet.next()) {student.setStuid(resultSet.getInt("stuid"));student.setStuname(resultSet.getString("stuname"));Subject subject = new Subject();subject.setSubname(resultSet.getString("subname"));subject.setSubid(resultSet.getInt("subid"));subjects.add(subject);}student.setSubjects(subjects);return student;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (preparedStatement != null) {preparedStatement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return null;}
}

3.在demo中打印查询结果

package com;import bean.Student;
import bean.Subject;
import dao.StudentSubjectDaoImp;
import impl.StudentSubjectDao;import java.util.List;public class Demo2 {public static void main(String[] args) {StudentSubjectDao studentSubjectDao2 = new StudentSubjectDaoImp();Subject subject = studentSubjectDao2.getSubjectId(2);List<Student> students = subject.getStudents();System.out.println(subject.getSubname() + subject.getSubid());for (Student student1 : students) {System.out.println(student1.getStuname() + student1.getStuid());}System.out.println("___________________________");StudentSubjectDao studentSubjectDao = new StudentSubjectDaoImp();Student student = studentSubjectDao.getStudentId(1);List<Subject> subjects = student.getSubjects();System.out.println(student.getStuname());for (Subject subject2 : subjects) {System.out.println(subject2.getSubname());}}}

4.结果

ui2
张三1
李四2
王五3
赵六4
花花5
潇潇6
___________________________
张三
java
ui
h5
c++进程已结束,退出代码0

六、事务的应用

1.自动提交/手动提交切换

如果JDBC连接处于自动提交模式,默认情况下,则每个SQL语句在完成后都会提交到数据库。 事务使您能够控制是否和何时更改应用于数据库。它将单个SQL语句或一组SQL语句视为一个逻辑单 元,如果任何语句失败,则整个事务将失败。 要启用手动事务支持,而不是JDBC驱动程序默认使用的自动提交模式,请使用Connection对象的 setAutoCommit()方法。如果将boolean false传递给setAutoCommit(),则关闭自动提交。我们 可以传递一个布尔值true来重新打开它。

connection.setAutoCommit(false);//关闭事务自动提交
connection.setAutoCommit(true);

2.事务的提交commit和回滚rollback

conn.commit( );//提交事务
conn.rollback( );//回滚事务

可以在事务写完之后加上conn.commit( );来提交事务,在catch代码块报异常时写回滚rollback来撤销此次事务的操作。

3.保存点Savepoints

新的JDBC 3.0 Savepoint接口为提供了额外的事务控制。 设置保存点时,可以在事务中定义逻辑回滚点。如果通过保存点发生错误,则可以使用回滚方法来撤消 所有更改或仅保存在保存点之后所做的更改。

Connection对象有两种新的方法来管理保存点
- setSavepoint(String savepointName):定义新的保存点。它还返回一个Savepoint对象。
- releaseSavepoint(Savepoint savepointName):删除保存点。请注意,它需要一个Savepoint 对象作为参数。此对象通常是由setSavepoint()方法生成的保存点。

try{
//Assume a valid connection object conn
conn.setAutoCommit(false);
Statement stmt = conn.createStatement();
String SQL1 = "INSERT INTO Employees VALUES (106, 20, 'Rita', 'Tez')";
stmt.executeUpdate(SQL1);
Savepoint savepoint1 = conn.setSavepoint("Savepoint1");//设置保存点
String SQL2 = "INSERTED IN Employees VALUES (107, 22, 'Sita', 'Tez')";
stmt.executeUpdate(SQL2);
conn.commit();
}catch(Exception se){
conn.rollback(savepoint1);
}

上面一旦发生任何错误那么sql2就会执行失败,但是如果sql1的语句是对的,那么还可以正常执行

如过此处没有添加事务的概念,那么即使出现了其它的异常,只要sql语句没问题,数据库还是会改动数据,这样有些需要同步执行的数据操作就会出现错误,如转账,一个加钱另一个却没减钱就很不合理。

七、JDBC批处理

1.Statement批处理

- 使用createStatement()方法o创建Statement对象。
        - 使用setAutoCommit()将auto-commit设置为false 。 (设置为手动提交事务)
        - 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。
        - 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。
        - 最后,使用commit()方法提交所有更改。

Statement stmt = conn.createStatement();
conn.setAutoCommit(false);String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(200,'Zia','Ali', 30)";
stmt.addBatch(SQL);String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(201,'Raj','Kumar', 35)";
stmt.addBatch(SQL);String SQL = "UPDATE Employees SET age = 35 WHERE id = 100";
stmt.addBatch(SQL);int[] count = stmt.executeBatch();
conn.commit();

2.PreparedStatement批处理

String SQL = "INSERT INTO Employees (id, first, last, age) VALUES(?, ?, ?, ?)";PreparedStatement pstmt = conn.prepareStatement(SQL);//处理sql语句
conn.setAutoCommit(false);//切换手动提交事务pstmt.setInt( 1, 400 );//问号赋值
pstmt.setString( 2, "Pappu" );
pstmt.setString( 3, "Singh" );
pstmt.setInt( 4, 33 );pstmt.addBatch();pstmt.setInt( 1, 401 );
pstmt.setString( 2, "Pawan" );
pstmt.setString( 3, "Singh" );
pstmt.setInt( 4, 31 );pstmt.addBatch();int[] count = stmt.executeBatch();//执行所有sql语句conn.commit();

八、反射处理结果集

interface StudentSubjectDao
package impl;import bean.Student;import java.util.List;public interface StudentSubjectDao {List<Student> getAllStudent(Class cla);
}
StudentSubjectDaoImp implements StudentSubjectDao
package dao;import bean.Student;
import bean.Subject;
import impl.StudentSubjectDao;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class StudentSubjectDaoImp implements StudentSubjectDao {@Overridepublic List<Student> getAllStudent(Class cla) {Connection connection = null;PreparedStatement preparedStatement = null;ResultSet resultSet = null;try {Class.forName("com.mysql.cj.jdbc.Driver");String user = "root";String pass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, user, pass);String sql = "select * from student";preparedStatement = connection.prepareStatement(sql);resultSet = preparedStatement.executeQuery();List students = new ArrayList<>();//1.得到数据库的查询结果的列信息ResultSetMetaData metaData = resultSet.getMetaData();int columnCount = metaData.getColumnCount();//得到列名,返回列名数量String[] columnNames = new String[columnCount];//列名for (int i = 0; i < columnCount; i++) {columnNames[i]=metaData.getColumnName(i+1);//将结果集中的列名取出来
//                System.out.println(columnNames[i]);}//2.得到类中方法Method[] declaredMethods = cla.getDeclaredMethods();//通过传来的cla得到student方法while (resultSet.next()) {try {Object stu=cla.getDeclaredConstructor().newInstance();//创建对象for (String columnName : columnNames) {//遍历结果的列名String methodName = "set"+columnName;//set组合列名for (Method declaredMethod : declaredMethods) {//遍历方法集if (declaredMethod.getName().equalsIgnoreCase(methodName)){//如果student中某个的方法名和set加结果集列名组合的方法名一样declaredMethod.invoke(stu,resultSet.getObject(columnName));//调用这个set方法将结果集中的数据赋值给这个studen对象break;}}}students.add(stu);} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();}}return students;} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (preparedStatement != null) {preparedStatement.close();}if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}return null;}
}

demo

package com;import bean.Student;
import dao.StudentSubjectDaoImp;
import impl.StudentSubjectDao;import java.util.List;public class Demo3 {public static void main(String[] args) {StudentSubjectDao studentSubjectDao = new StudentSubjectDaoImp();List<Student> allStudent = studentSubjectDao.getAllStudent(Student.class);for (Student student : allStudent) {System.out.println(student.getStuid()+student.getStuname()+student.getTeacherid());}}
}

结果

1张三3
2李四1
3王五3
4赵六1
5花花1
6潇潇2

九、封装工具类

通过工具类可以极大地简化代码

DBUtils
package util;import java.sql.*;
import java.util.List;public class DBUtils {private Connection connection = null;private PreparedStatement preparedStatement = null;private ResultSet resultSet = null;private int count;//统计增删改操作受影响的行数String userName = "root";String userPass = "123456";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";//加载驱动static {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 获得连接*/protected Connection getConnection() {try {connection = DriverManager.getConnection(url, userName, userPass);} catch (SQLException e) {e.printStackTrace();}return connection;}/*** 得到预状态通道*/protected PreparedStatement getPreparedStatement(String sql) {try {preparedStatement = getConnection().prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return preparedStatement;}/*** 绑定参数* List保存的是给占位符所赋的值,即?部分的值*/protected void param(List list) {if (list != null && list.size() > 0) {for (int i = 0; i < list.size(); i++) {try {preparedStatement.setObject(i + 1, list.get(i));} catch (SQLException e) {e.printStackTrace();}}}}/*** 更新操作*/protected int upData(String sql, List list) {try {getPreparedStatement(sql);//获得预状态通道param(list);//补全sql中问号部分count = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return count;}/*** 查询操作*/protected ResultSet query(String sql, List list) {try {getPreparedStatement(sql);//获得预状态通道param(list);//补全sql中问号部分resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}/*** 关闭资源*/protected void closeAll() {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}}
StudentSubjectDaoImp extends DBUtils implements StudentSubjectDao(继承工具类以直接使用工具类DBUtils中的方法)
public class StudentSubjectDaoImp extends DBUtils implements StudentSubjectDao {
@Overridepublic Student getByStudentId(int stuid) {Student student = new Student();try {String sql="select * from student where stuid=?";List list = new ArrayList();list.add(stuid);ResultSet resultSet = query(sql,list);while (resultSet.next()){student.setStuid(resultSet.getInt("stuid"));student.setStuname(resultSet.getString("stuname"));}} catch (SQLException e) {e.printStackTrace();}return student;}
}

demo(通过学号查找人)

package com;import bean.Student;
import dao.StudentSubjectDaoImp;
import impl.StudentSubjectDao;public class Demo4 {public static void main(String[] args) {StudentSubjectDao studentSubjectDao = new StudentSubjectDaoImp();Student student = studentSubjectDao.getByStudentId(2);System.out.println(student.getStuid()+student.getStuname());}
}

十、属性文件

用来存储用户名密码url等信息

db.properties
userName=root
userPass=123456
url=jdbc:mysql://localhost:3306/practice?serverTimezone=UTC
driver=com.mysql.cj.jdbc.Driver

加载驱动的两种方法

//方法1
InputStream inputStream = 当前类名.class.getClassLoader()         .getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(inputStream);
dirverName = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("user");
password = properties.getProperty("password");//方法2
ResourceBundle bundle = ResourceBundle.getBundle("db");
driver = bundle.getString("driver");
url = bundle.getString("url");
userName = bundle.getString("userName");
userPass = bundle.getString("userPass");
Class.forName(driver);

完整DBUtils

package util;import java.sql.*;
import java.util.List;
import java.util.ResourceBundle;public class DBUtils {private Connection connection = null;private PreparedStatement preparedStatement = null;private ResultSet resultSet = null;private int count=0;//统计增删改操作受影响的行数private static String userName;private static String userPass;private static String url;private static String driver;//加载驱动static {try {ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");userName = bundle.getString("userName");userPass = bundle.getString("userPass");Class.forName(driver);} catch (ClassNotFoundException e) {e.printStackTrace();}}/*** 获得连接*/protected Connection getConnection() {try {connection = DriverManager.getConnection(url, userName, userPass);} catch (SQLException e) {e.printStackTrace();}return connection;}/*** 得到预状态通道*/protected PreparedStatement getPreparedStatement(String sql) {try {preparedStatement = getConnection().prepareStatement(sql);} catch (SQLException e) {e.printStackTrace();}return preparedStatement;}/*** 绑定参数* List保存的是给占位符所赋的值,即?部分的值*/protected void param(List list) {if (list != null && list.size() > 0) {for (int i = 0; i < list.size(); i++) {try {preparedStatement.setObject(i + 1, list.get(i));} catch (SQLException e) {e.printStackTrace();}}}}/*** 更新操作* 参数含义(sql语句,?占位符上的值)* @return 返回受影响的行数*/protected int upData(String sql, List list) {try {getPreparedStatement(sql);//获得预状态通道param(list);//补全sql中问号部分count = preparedStatement.executeUpdate();} catch (SQLException e) {e.printStackTrace();}return count;}/*** 查询操作* 参数含义(sql语句,?占位符上的值)* @return 查询数据库返回的结果集*/protected ResultSet query(String sql, List list) {try {getPreparedStatement(sql);//获得预状态通道param(list);//补全sql中问号部分resultSet = preparedStatement.executeQuery();} catch (SQLException e) {e.printStackTrace();}return resultSet;}/*** 关闭资源*/protected void closeAll() {try {if (connection != null) {connection.close();}if (preparedStatement != null) {preparedStatement.close();}if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}}}

十一、连接池

*连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数 据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户 也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连 接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数 以及每个连接的最大使用次数、最大空闲时间等等,也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。

*连接池用linklist默认初始化十个连接,其中有commit,rollback等常规方法,其中close方法在关闭资源时并不是真的关闭了资源,而是使用linklist的addlast方法将这个连接放在了连接池尾部,以待下次调用。
*最小连接数 :
是数据库一直保持的数据库连接数,所以如果应用程序对数据库连接的使用量不大,将有大量的数据库资源被浪费。
*初始化连接数:
连接池启动时创建的初始化数据库连接数量。
*最大连接数
是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队列中。
*最大等待时间:
当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为 0 或者负数 使得无限等待( 根据不同连接池配置 ) 。
DBCP C3P0 DRUID
最小连接数 minldle(0) minPoolSize(3) mindle(o)
初始化连接数 initialSize(0) initialPoolSize(3) initialSize(0)
最大连接数 maxTotal(8) maxPoolSize(15) maxActive(8)
最大等待时间 maxWaitMillis(毫秒) maxldleTime(0秒) maxWait(毫秒)

1.DBCP(不可以自动回收空闲连接)

先在lib文件夹下注入jia包

将DBUtils部分的加载驱动和获得连接部分做修改

 private static BasicDataSource basicDataSource = new BasicDataSource();
//加载驱动static {ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");userName = bundle.getString("userName");userPass = bundle.getString("userPass");basicDataSource.setUsername(userName);//获取用户名basicDataSource.setPassword(userPass);//获取密码basicDataSource.setUrl(url);//获取urlbasicDataSource.setDriverClassName(driver);//获取驱动位置basicDataSource.setInitialSize(10);//设置初始连接数}/*** 获得连接*/protected Connection getConnection() {try {connection = basicDataSource.getConnection();//获得连接} catch (SQLException e) {e.printStackTrace();}return connection;}

2.C3P0(自动回收空闲连接)

在lib下注入jar包,src目录下创建c3p0-config.xml文件

C3P0通过配置文件来完成所有操作,因此将原先db.properties中的信息写入配置文件

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><default-config><property name="driverClass">com.mysql.cj.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql://localhost:3306/practice?serverTimezone=UTC</property><property name="user">root</property><property name="password">123456</property><!-- 等待连接的超时时间,默认为0,代表无限等待,单位是毫秒 --><property name="checkoutTimeout">30000</property><!-- 检查空闲连接  默认为0 代表不检查 --><property name="idleConnectionTestPeriod">30</property><!-- 初始化连接 --><property name="initialPoolSize">10</property><!-- 最大空闲时间,超过这个时间的连接将被丢弃,默认为0,代表永远不关闭 --><property name="maxIdleTime">30</property><!-- 最大连接数 --><property name="maxPoolSize">100</property><!-- 最小连接数 --><property name="minPoolSize">10</property><!-- preparedStatement的缓存大小 --><property name="maxStatements">200</property><!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3 --> <property name="AcquireIncrement">5</property></default-config></c3p0-config>

写入配置文件后不用再手动加载驱动 ,static加载驱动部分不用再写

private static ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();/*** 获得连接*/protected Connection getConnection() {try {connection = comboPooledDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}

3.Druid德鲁伊(阿里开发)

        它不仅仅是一个数据库连接池,它还包含一个 ProxyDriver(代理驱动),一系列内置的JDBC 组件库,一个 SQL Parser(sql 解析器 ) 。支持所有 JDBC 兼 容的数据库,包括Oracle 、 MySql 、 Derby 、 Postgresql 、 SQL Server 、 H2 等等。
        Druid针对 Oracle 和 MySql 做了特别优化,比如 Oracle 的 PS Cache 内存占用优化, MySql 的 ping 检测优化。
        Druid提供了 MySql 、 Oracle 、 Postgresql 、 SQL-92 的 SQL 的完整支持,这是一个手写的高性能 SQL Parser,支持 Visitor 模式,使得分析 SQL 的抽象语法树很方便。 简单SQL 语句用时 10 微秒以内,复杂 SQL 用时 30 微秒。
        通过Druid 提供的 SQL Parser 可以在 JDBC 层拦截 SQL 做相应处理,比如说分库分表、审计等。 Druid 防御SQL注入攻击的WallFilter 就是通过 Druid 的 SQL Parser 分析语义实现的。
        Druid 是目前比较流行的高性能的,分布式列存储的 OLAP 框架 ( 具体来说是 MOLAP) 。它有如下几个特点
一 . 亚秒级查询

        druid提供了快速的聚合能力以及亚秒级的 OLAP 查询能力,多租户的设计,是面向用户分析应用的理想方式。
二 . 实时数据注入
druid 支持流数据的注入,并提供了数据的事件驱动,保证在实时和离线环境下事件的实效性和统一性
三 . 可扩展的 PB 级存储
druid 集群可以很方便的扩容到 PB 的数据量,每秒百 万级别的数据注入。即便在加大数据规模的情况下,也能保证时其效性
四 . 多环境部署
druid 既可以运行在商业的硬件上,也可以运行在云上。它可以从多种数据系统中注入数据,包括
hadoop , spark , kafka , storm 和 samza 等
五 . 丰富的社区
使用方法:
在lib下注入jar包
获得对象,手动获取地址,需要注意德鲁伊默认最大活跃连接数量是8因此如果要设置大于8的活跃连接数应该先设置上限

 //Druid对象private static DruidDataSource druidDataSource = new DruidDataSource();//加载驱动static {ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");userName = bundle.getString("userName");userPass = bundle.getString("userPass");druidDataSource.setUrl(url);druidDataSource.setUsername(userName);druidDataSource.setPassword(userPass);druidDataSource.setDriverClassName(driver);druidDataSource.setMaxActive(20);//设置活跃连接上限druidDataSource.setInitialSize(20);//设置连接数}/*** 获得连接*/protected Connection getConnection() {try {connection = druidDataSource.getConnection();} catch (SQLException e) {e.printStackTrace();}return connection;}

五、JDBC(复习)相关推荐

  1. 软件工程导论第五章复习总结附思维导图及部分习题答案

    软件工程导论第五章复习总结附思维导图及部分习题答案 总体设计 一.设计过程 1.设想提供选择的方案 2.选取合理的方案 3.推荐最佳方案 4.功能分解 5.设计软件结构 6.设计数据库 7.制定测试计 ...

  2. 郑莉老师c++第五版 复习笔记

    本文是郑莉老师c++第五版的复习笔记 文章目录 第0章:学习怎么学习 先修正下之前关于学习的错误认识 1.理科一定要学系统课,不要零零碎碎的学.零零碎碎就算学几十个小时反而也是浪费时间还会误入歧途. ...

  3. Mysql(五) JDBC

    一.JDBC JDBC(Java DataBase Connectivity) 是Java 数据库连接API.     JDBC完成三件事: 与一个数据库连接          向数据库发送SQL语句 ...

  4. Java之十五 JDBC编程

    视频课堂:https://edu.csdn.net/course/play/8222 有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事.换言之,有了JDBCAPI,就不必为访问Sybase ...

  5. Java基础一到五章复习笔记

    目录 第一章 第二章 java语言特点 JDK和JRE 转义字符: 注释: 相对路径和绝对路径 常用dos命令 第三章 变量三要素: 加号+的使用: Java API 基本数据类型转换 强制类型转换 ...

  6. 2020 操作系统第五天复习(知识点总结)

    文章目录 1:文件系统中,文件访问控制信息存储的合理位置是 2:设F1的当前引用计数为1,先建立F1的符号链接文件F2,再建立F1的硬链接文件F3,然后删除F1,此时F2和F3的引用计数分别是 3:伙 ...

  7. 【笔记整理】通信原理第五章复习——模拟信号的数字化

    5.1 引言 数字通信系统的优点: (1)抗干扰能力强 (2)传输差错可控 (3)便于现代化数字信号处理技术来对数字信息进行处理 (4)易于集成化 (5)易于加密处理,保密强度高 利用数字通信系统传输 ...

  8. C语言程序设计谭浩强第五版复习梳理2

    第2章 算法--程序的灵魂 前言:前两章都是c语言基础知识,软考还有考研笔试可能会考,下一章开始学的才是真正的编程. 2.1程序=算法+数据结构 算法+数据结构=程序 数据结构: 对数据的描述.在程序 ...

  9. 小学五年级计算机备考方案,五年级数学备考计划_备考经验

    为全面提高学生的数学成绩而进行全面.系统.有针对性的总复习,下面是小编为大家整理的关于五年级数学备考计划,希望对您有所帮助.欢迎大家阅读参考学习! 五年级数学备考计划 一.指导思想 以<义务教育 ...

  10. foxpro 打印 字体_【部编版同步复习】16年级上册期中预测卷,可打印!

    小语说: 开学以后,不仅要认真学习,还要注意复习之前的知识点.小语给你们准备了小学语文部编版1-6年级每课一练,快来学习收藏.(点击下方蓝色字体查看完整版,可打印下载哦!) 点击蓝字标题  可查看相关 ...

最新文章

  1. Windows下Nginx+Tomcat整合的安装与配置
  2. 为什么 Python 的 Range 要设计成左开右闭区间?
  3. 【转】推荐计算机科学类的经典书籍 3
  4. 洛谷 P1851 好朋友
  5. Ember入门指南——教程目录
  6. java的abstract的意思_java – spring中的abstract =“true”是什么意思?
  7. 记录平时编程或者阅读英文文档的时候不认识的英文单词
  8. 怎样准备阿里技术面试_如何准备技术面试
  9. 关于Visual C#.NET数据库开发经典案例解析(附光盘两张)(珍藏版)—的读后感...
  10. python列表常用の操作
  11. 去中心化交易所协议0x protocol A轮融资获IOSG Ventures 支持
  12. [题解]诸侯安置(dp+组合)
  13. 数据库系统概论第五版(王珊)-系统篇(十二)
  14. 有关嵌入式、单片机、51单片机、STM32、的一些概念详解
  15. 无人车传感器 IMU 深入剖析
  16. 诛仙服务器技能修改,2021年5月21日正式服技能修改公告
  17. 中国月度、年度NDVI/植被覆盖空间分布数据分享(1986-2021)
  18. 个人如何选择阿里云香港服务器?
  19. coc跑团san数值规则_【规则】克苏鲁coc跑团游戏术语/黑话,第三篇教学。
  20. C#生成word的几种方式。过程及问题记录。

热门文章

  1. 知乎:有哪些让你相见恨晚的 PPT 制作技术或知识?
  2. 万维钢:怎样做读书笔记
  3. (附源码)springboot电影院售票与管理系统 毕业设计011449
  4. css筋斗云,CSS3 七龙珠筋斗云动画
  5. Java小程序 个人缴税
  6. SSL-ZYC 2124 涂色
  7. 游戏三级分类部分代码
  8. android 计步器 计算当前的行走步数
  9. 【入门恩师】 --极致强压下的Linux学习,感谢马哥
  10. 云服务器有token_配置node服务器并且链接微信公众号接口配置