使用步骤
- 导入包:需要包含包含数据库编程所需的JDBC类的包。大多数情况下,使用
import java.sql.*就足够了。 - 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道
- 注册驱动程序最常见的方法是使用Java的Class.forName()方法,将驱动程序的类文件动态加载到内存 中,并将其自动注册
- 打开连接:需要使用DriverManager.getConnection()方法创建一个Connection对象,该对象表 示与数据库的物理连接。
- url:jdbc:mysql://localhost:3306/yhp2?serverTimezone=UTC
- url:jdbc:mysql://localhost:3306/数据库名? useSSL=false&useUnicode=true&characterEncoding=UTF-8
- 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。
- 从结果集中提取数据:需要使用相应的
ResultSet.getXXX()方法从结果集中检索数据 释放资源:需要明确地关闭所有数据库资源,而不依赖于JVM的垃圾收集
- 为确保连接关闭,您可以在代码中提供一个“finally”块。一个finally块总是执行,不管是否发生异常。 要关闭上面打开的连接,你应该调用close()
package com.jdbc;import java.sql.*;public class Demo1 {public static void main(String[] args) {Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {//1. 加载驱动Class.forName("com.mysql.cj.jdbc.Driver");//2. 获得链接String userName = "root";String passWord = "123456 ";String url = "jdbc:mysql://localhost:3306/practice?serverTimezone=UTC";connection = DriverManager.getConnection(url, userName, passWord);//3. 定义 sql,创建状态通道(进行sql语句的发送)statement = connection.createStatement();resultSet = statement.executeQuery("select * from department");//执行查询//4. 取出结果集信息while(resultSet.next()){// 取出数据System.out.println(resultSet.getString("departmentName"));}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException throwables) {throwables.printStackTrace();} finally {try {if (resultSet != null) {resultSet.close();}if (statement != null) {statement.close();}if (connection != null) {connection.close();}} catch (SQLException throwables) {throwables.printStackTrace();}}}}
curd
- 为确保连接关闭,您可以在代码中提供一个“finally”块。一个finally块总是执行,不管是否发生异常。 要关闭上面打开的连接,你应该调用close()
对于查询数据,使用
statement.executeQuery返回一个ResultSet对象- 对于增删改,使用
statement.executeUpdate返回的是受影响的列数 intSQL 注入
通过把 SQL 命令插入到 Web 表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令
具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎 执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据 库,而不是按照设计者意图去执行SQL语句。
String username ="admin";String password=" 'abc' or 1=1 ";String sql="select * from users where username= '"+username+"' and password="+password;
PreparedStatement(预状态通道)
该PreparedStatement的接口扩展了Statement接口
JDBC中的所有参数都由?符号,这被称为参数标记。在执行SQL语句之前,必须为每个参数提供值。
所述的setXXX()方法将值绑定到所述参数,其中XXX代表要绑定到输入参数的值的Java数据类型。如果 忘记提供值,将收到一个SQLException。
每个参数标记由其顺序位置引用。第一个标记表示位置1,下一个位置2等等。该方法与Java数组索引不 同,从0开始。
关闭 PreParedStatement 对象
String sql = "select * from parctice where userName=? and passWord=?";prepareStatement pps = connection.prepareStatement(sql);String uname='aa';String pword='123123';//给占位符赋值pps.setString(1, uname);pps.setString(2, pword);//给占位符赋值resultSet = pps.exeucteQuery();
- statement属于状态通道,PreparedStatement属于预状态通道
- 预状态通道会先编译sql语句,再去执行,比statement执行效率高
- 预状态通道支持占位符?,给占位符赋值的时候,位置从1开始
- 预状态通道可以防止sql注入,
- 原因:预状态通道在处理值的时候以字符串的方式处理
多表操作
- 数据库通过外键建立两表关系
- 实体类通过属性的方式建立两表关系 实体类要求:类名=表名,列名=属性名
一对多(老师->学生)
多对一
一对一
多对多
数据库事务
一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操作的一个执行单元
四大特点
- 原子性 actomicity
- 一致性 consistency
- 隔离性 isolation
- 持久性 durability
自动提交
要启用手动事务支持,而不是JDBC驱动程序默认使用的自动提交模式,请使用Connection对象的 setAutoCommit()方法。如果将boolean false传递给setAutoCommit(),则关闭自动提交。我 们可以传递一个布尔值true来重新打开它
完成更改后,我们要提交更改,然后在连接对象上调用commit()方法,如下所示: conn.commit( );
否则,要使用连接名为conn的数据库回滚更新,请使用以下代码 -conn.rollback( );
Savepoints
JDBC 批处理
Statement批处理
以下是使用语句对象的批处理的典型步骤序列
- 使用createStatement()方法创建Statement对象。
- 使用setAutoCommit()将auto-commit设置为false 。
- 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。
- 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。
- 最后,使用commit()方法提交所有更改。
PreparedStatement批处理
- 使用占位符创建SQL语句。
- 使用prepareStatement() 方法创建PrepareStatement对象。
- 使用setAutoCommit()将auto-commit设置为false 。
- 使用addBatch()方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。
- 在创建的语句对象上使用executeBatch()方法执行所有SQL语句。
- 最后,使用commit()方法提交所有更改。
反射处理结果集
//得到数据库中的所有的列有哪些?ResultSetMetaData metaData = rs.getMetaData();//返回数据库中的相关信息int count=metaData.getColumnCount();//得到列数String[] columnnames=new String[count];for (int i = 0; i < count; i++) {// System.out.println(metaData.getColumnName(i+1));//列的位置从1开始columnnames[i]=metaData.getColumnName(i+1);}//得到实体类中的所有的方法Method[] methods =cla.getDeclaredMethods();while(rs.next()){Object s=cla.newInstance();//调取无参构造创建对象for (String columnname : columnnames) {String name="set"+columnname;//setstuidfor (Method method : methods) {if(method.getName().equalsIgnoreCase(name)){method.invoke(s,rs.getObject(columnname));//执行了对应set方法break;}}}list.add(s);}
工具类的定义
properties文件保存数据库信息-特点:key-value存储方式
db.properties
driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/yhpuser=rootpassword=123456
工具类中读取属性文件
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");static{//参数只写属性文件名即可,不需要写后缀ResourceBundle bundle = ResourceBundle.getBundle("db");driver = bundle.getString("driver");url = bundle.getString("url");username = bundle.getString("user");password = bundle.getString("password");}
使用ResourceBundle访问本地资源 在设计时,我们往往需要访问一些适合本地修改的配置信息,如果作为静态变量,那么每次修改都 需要重新编译一个class,.config保存此类信息并不适合,这时我们需要ResourceBundle。 通过ResourceBundle,我们需要访问位于/WEB-INF/classes目录下的一个后缀名为properties的文本 类型文件,从里面读取我们需要的值。
连接池
连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数 据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户 也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。
而连接的建立、断开都由连接池自身来管理。
同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数 以及每个连接的最大使用次数、最大空闲时间等等,也可以通过其自身的管理机制来监视数据库连接的 数量、使用情况等。
自定义连接池
最小连接数:
是数据库一直保持的数据库连接数,所以如果应用程序对数据库连接的使用量不大,将有大量的数据库 资源被浪费
初始化连接数:
最大连接数:
是连接池能申请的最大连接数,如果数据库连接请求超过此数,后面的数据库连接请求被加入到等待队 列中。
最大等待时间:
当没有可用连接时,连接池等待连接被归还的最大时间,超过时间则抛出异常,可设置参数为0或者负数使得无限等待(根据不同连接池配置)。
