目录
🍐什么是JDBC
🍐前期配置
🍐连接数据库
🍐JDBC操作数据库
基本操作执行静态SQL语句
预编译操作执行动态SQL语句
🍐处理返回结果
查询结果
增删改结果
🍐JDBC处理事务
🍐Druid连接池
🍐关闭资源
🍐总结
🍐什么是JDBC
JDBC就是通过Java语言操作关系型数据库的一套API, 使用Java代码对数据库中的数据完成增删改查的功能
🍐前期配置
1. mysql的驱动连接jar包
2. druid连接池jar包
🍐连接数据库
1. 注册驱动 :告诉Java要注册的是什么数据库管理系统,.
不同数据库管理系统的驱动在java中是Driver接口的实现类, 按照规范给出自己的逻辑, 在mysql的Driver类中有一个静态代码块, 使用DriverManager注册当前的Driver, 完成注册驱动.
2. 使用DriverManager获取连接
//注册驱动Class.forName("com.mysql.jdbc.Driver");//使用DriverManager获取连接//参数一:连接mysql数据库管理系统 本机IP下的3306端口 test数据库 禁用安全模式//参数二:数据库用户名//参数三:数据库密码Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?useSSL=false","root","root");
🍐JDBC操作数据库
基本操作执行静态SQL语句
1. 通过连接创建Statement执行对象
2. 使用Statement执行对象的executeQuery / executeUpdate 操作提前写好的静态SQL语句
Statement statement = connection.createStatement();ResultSet resultSet = statement.executeQuery("SELECT * FROM person");
预编译操作执行动态SQL语句
SQL注入问题:先说一下为什么会出现预编译执行对象, 在某种场景下, 我们知道筛选条件, 但并不确定筛选条件的值的情况下, 如果使用执行对象 进行拼接的话, 那么会产生SQL注入的问题
//举个例子String name = "张三";String password = "1 OR 1=1";Statement statement = connection.createStatement("SELECT * FROM person WHERE name ='"+name+"' AND password = "+password);//拼接的结果是SELECT * FROM person WHERE name='张三' AND password = 1 OR 1=1//这种拼接的后果就是 无论张三的密码是什么 用这个方式都能登录成功
另外在整理的时候犯了个大错误, 如图!!!!!谨记谨记o(╥﹏╥)o
所以说预编译是不能指定字段的!!!!只能对sql语句的限制条件内容进行预编译!
那么如何正确使用预编译执行对象:
1. 使用连接创建预编译对象PreStatement 并给出需要预编译的SQL, 不确定的条件值写?
2. 给? 赋值, 一般可以写一个scanner, 将控制台的内容作为查询条件
3. 使用PreStatement执行对象的executeQuery / executeUpdate 执行SQL
//想要按照暂时还没指定好的两个条件去查询//使用预编译执行对象PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM person WHERE id<? AND money> ?");//给不确定的内容赋值,是什么类型就使用set类型 的方法//参数一:第几个问号//参数二:赋值内容preparedStatement.setObject(1,3);preparedStatement.setObject(2,3000);
🍐处理返回结果
返回结果分为两种情况, 一种是DQL查询语句会返回的结果集, 另一种是DML操作语句返回影响数据的条数
查询结果
使用executeQuery返回的结果是ResultSet结果集, 有可能查不到数据, 也有可能一条或者很多条,ResultSet封装了一个next()方法用来判断是否还有下一条数据, 又封装了get类型()的方法用来从数据库中获取不同字段的值
//创建一个ArrayList集合, 将数据库中每条数据封装到Person对象中, 并将查询并封装好的每个Person对象存储到集合中ArrayList<Person> persons = new ArrayList<>();//判断是否还有下一条数据while (resultSet.next()){//根据列名和列的数据类型 获取到数据 添加到集合中的person对象中int id = resultSet.getInt("id");String name = resultSet.getString("name");String password = resultSet.getString("password");String money = resultSet.getString("money");persons.add(new Person(id,name,password,money));}persons.forEach(p-> System.out.println(p));
增删改结果
对于DML语句的增删改返回的是int值: 受影响的行数, 直接打印或者根据业务进行处理就ok
public class Test {public static void main(String[] args) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?useSSL=false","root","root");PreparedStatement preparedStatement = connection.prepareStatement("UPDATE person SET name = ? WHERE id = ?");//给不确定的内容赋值,是什么类型就使用set类型 的方法//参数一:第几个问号//参数二:赋值内容preparedStatement.setObject(1,"tianqi");preparedStatement.setObject(2,2);int i = preparedStatement.executeUpdate();System.out.println("执行sql后受影响的行数是:"+i);}}
🍐JDBC处理事务
当没有设置手动事务的情况下, 每条语句就是一个事务, 举例转账业务, 使用自动事务, 可能会出现一条成功, 一条失败的情况, 但这并不符合我们想要的逻辑
//错误案例!!!!statement.executeUpdate("UPDATE person SET money=money-3000 WHERE name = '张三'");int i = 1/0 //加个除零异常, 则下面代码执行不成功statement.executeUpdate("UPDATE person SET money=money+3000 WHERE name = '李四'");
如何使用JDBC处理事务? --------使用连接对象调用方法
1. setAutoCommit(false) :使用手动事务, 开启事务后, 所有执行的sql组成一个事务
2. commit() :提交事务 , 结束本次手动事务
3. rollback() :回滚本次事务到开始事务前的状态点
使用步骤:
1. 通过连接对象开启手动事务
2. 将多个sql代码组成的一个需求用try catch包上
3. 如果执行完最后一行sql就commit提交, 如果捕获到异常,在catch中rollback回滚
connection.setAutoCommit(false);try{statement.executeUpdate("UPDATE person SET money=money-3000 WHERE name = '张三'");statement.executeUpdate("UPDATE person SET money=money+3000 WHERE name = '李四'");mit();}catch(Exception e){connection.rollback();}
🍐Druid连接池
Java定义了连接池的规范为DataSource接口, 不同厂商做的连接池作为该接口的实现类进而完成自己的功能
Druid连接池在创建的过程中, 将数据库的注册, url, 用户名以及密码等信息封装到一个配置文件中, 在创建Druid连接池时给一个配置文件对象, 就能创建一个连接
db.properties:
driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://127.0.0.1:3306/test?uesSSL=falseusername=rootpassword=rootinitialSize=5maxActive=5maxWait=3000
DruidTest:
import com.abc.entity.Person;import com.alibaba.druid.pool.DruidDataSourceFactory;import javax.sql.DataSource;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.Properties;public class DruidTest {private static DataSource dataSource;static{Properties prop = new Properties();try {prop.load(ClassLoader.getSystemClassLoader().getResourceAsStream("db.properties"));dataSource = DruidDataSourceFactory.createDataSource(prop);} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) throws SQLException {Connection connection = dataSource.getConnection();PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM person");ResultSet resultSet = preparedStatement.executeQuery();while (resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");String password = resultSet.getString("password");String money = resultSet.getString("money");Person person = new Person(id,name,password,money);System.out.println(person);}resultSet.close();preparedStatement.close();connection.close();}}
🍐关闭资源
使用完记得关闭资源, 避免浪费
关闭结果集
关闭执行对象
关闭连接对象
🍐总结
为了节省资源, 建议使用连接池创建连接对数据库中的数据进行操作
1. 创建配置文件
2. 加载配置文件
3. 创建连接池对象 , 传入配置文件对象
4. 使用连接池对象创建连接
5. 使用连接对象创建执行对象
6. 执行sql语句
7. 处理返回结果
8. 关闭资源