• JDBC总结


    目录

    jdbc概念

    jdbc本质

    jdbc好处

    jdbc操作数据库

    表用例-db数据库的emp表

    DriverManager(驱动管理类)

    注册驱动

    获取数据库连接

    参数

    关于url

    Connection

    获取sql执行的对象

    事务管理

    mysql管理事务

    jdbc管理事务(Connection接口中定义了3个对应的方法)

    Statement

    ResultSet

    获取查询结果

    获取整个行 

    获取行中的每个元素 

    ResultSet过程

    ResultSet使用步骤

    sql注入

    sql注入测试用例-user表

    PreparedStatement

    使用

    获取PreparedStatement对象:

    设置参数值

    执行sql

    解决sql注入

    PreparedStatement好处

    如何理解预编译

    数据库连接池

    简介

    好处:

    不使用数据库连接池

    使用数据库连接池

    连接池的连接实现

    常见的数据库连接池

    Druid(德鲁伊)

    Driud使用步骤

    配置文件

    表用例-emp

    jdbc概念

    jdbc:(java database connectivity)java数据库连接,其就是使用java语言来操作数据库的一套API,其定义了操作所有关系型数据库的一套规则。

    注意:jdbc定义了一套接口,通过这套接口就可以操作不同的关系型数据库

    jdbc本质

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

    jdbc好处

    • 各个数据库厂商使用相同的接口,java代码不需要针对不同数据库分别开发
    • 可以随时替换底层的数据库,访问数据库的java代码基本不变

    jdbc操作数据库

    过程:

    1. 在java代码里定义好sql语句
    2. 将sql法给mysql数据库
    3. mysql数据库执行完sql之后给我们返回结果

    使用前提:导入对应数据库的驱动jar包(实现类)

    表用例-db数据库的emp表

    1. public class JDBCDemo {
    2. public static void main(String[] args) throws Exception {
    3. //注册驱动——加载driver类至内存(可以省略不写)
    4. Class.forName("com.mysql.jdbc.Driver");
    5. //连接的数据库地址——协议、域名、端口号、要连接的数据库
    6. String url="jdbc:mysql://127.0.0.1:3306/db";
    7. //数据库设的用户名
    8. String u="root";
    9. //为数据库设的密码
    10. String p="root";
    11. //获取数据库连接
    12. Connection connection = DriverManager.getConnection(url, u, p);
    13. //定义sql语句
    14. String sql="update emp set salary=8500 where id=3";
    15. //获取执行sql的对象(传输器)statement
    16. Statement statement = connection.createStatement();
    17. //执行sql——返回的i为影响行数
    18. int i = statement.executeUpdate(sql);
    19. //处理结果
    20. System.out.println(i);
    21. //释放资源
    22. statement.close();
    23. connection.close();
    24. }
    25. }

    DriverManager(驱动管理类)

    作用:

    1. 注册驱动
    2. 获取数据库连接

    注意:DriverManager是一个工具类,里面很多静态方法

    注册驱动

    注册驱动:Class.forName("com.mysql.jdbc.Driver");

    1. //Driver类内
    2. static {
    3. try {
    4. //注册驱动
    5. DriverManager.registerDriver(new Driver());
    6. } catch (SQLException var1) {
    7. throw new RuntimeException("Can't register driver!");
    8. }
    9. }

    提示:

    • mysql 5之后的驱动包,可以省略注册驱动的步骤(Class.forName("com.mysql.jdbc.Driver"))
    • 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类

    获取数据库连接

    参数

    • url:连接路径
    • user:用户名
    • password:密码

    关于url

    Connection

    作用:

    • 获取执行sql的对象
    • 管理事务

    获取sql执行的对象

    普通执行sql对象:Statement createStatement()

    预编译sql的sql执行对象:PreparedStatement prepareStatement(sql)

    执行存储过程的对象:CallableStatement prepareCall(sql)

    事务管理

    mysql管理事务

    jdbc管理事务(Connection接口中定义了3个对应的方法)

    1. public class JDBCDemo {
    2. public static void main(String[] args) throws Exception {
    3. Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","root");
    4. String sql1="update emp set salary=8500 where id=3";
    5. String sql2="update emp set salary=8500 where id=4";
    6. Statement statement = connection.createStatement();
    7. try {
    8. //开启事务-手动提交
    9. connection.setAutoCommit(false);
    10. int i1 = statement.executeUpdate(sql1);
    11. int i2 = statement.executeUpdate(sql2);
    12. System.out.println(i1+""+i2);
    13. //提交事务
    14. connection.commit();
    15. }catch (Exception e){
    16. //回滚事务
    17. connection.rollback();
    18. //打印异常信息
    19. e.printStackTrace();
    20. }
    21. statement.close();
    22. connection.close();
    23. }
    24. }

    Statement

    作用:执行sql语句

    int executeUpdate(sql):用来执行DML、DDL语句

    返回值

    • DML语句执行完会返回影响行数,影响行数不为0则成功
    • DDL语句执行完,执行成功也会返回0

    RestultSet executeQuery(sql):用于执行DQL语句

    返回值:ResultSet结果集对象 

    1. @Test
    2. public void testdb() throws Exception {
    3. Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","root");
    4. String sql1="update emp set salary=8400 where id=3";
    5. String sql2="drop database db1";
    6. Statement statement = connection.createStatement();
    7. //执行DML语句,返回影响行数
    8. int i1 = statement.executeUpdate(sql1);
    9. //执行DDL语句,DDL语句执行完一般不报异常就ok
    10. int i2 = statement.executeUpdate(sql2);
    11. System.out.println(i1>0?"执行成功":"执行失败");
    12. System.out.println(i2);
    13. statement.close();
    14. connection.close();
    15. }

    ResultSet

    作用:封装了DQL查询语句的结果集对象

    获取查询结果

    获取整个行 

    获取行中的每个元素 

    xxx getXxx(参数):获取列数据,最终返回列数据

    xxx:数据类型=>与对应列的数据类型保持一致

    eg:

    • int getInt(1):获取该行第一列(该列字段为int类型)的数据
    • String getString(2):获取该行第二列(该列字段为String类型)的数据
    • Object getObject(3):获取该行第三列(该列字段为随意类型)的数据

    参数:

    1. int类型的列数(列数从1开始)=>表示该行第几列的元素
    2. String类型的列名=>表示该行的特定列名的元素

    ResultSet过程

     

    ResultSet会将上面查询的表数据都封装起来,内部有个游标(一个箭头)此游标默认指向当前数据行的上一行,获取数据则游标会向下移动一行,移动一行后,要判断当前行是不是有效行(有数据就是有效行),如果是有效行就开始可以从头一个一个的获取数据了,获取完之后再想获取第二行则游标再往下移动一行,如此循环往复

    ResultSet使用步骤

    1. 游标向下移动一行,判断该行是否有数据:next()
    2. 获取数据:getxxx(参数)

    1. @Test
    2. public void testRes() throws Exception {
    3. Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","root");
    4. String sql="select * from emp where id<4";
    5. Statement statement = connection.createStatement();
    6. ResultSet resultSet = statement.executeQuery(sql);
    7. //处理返回结果
    8. //光标向下移动一行,并且判断当前行是否有数据
    9. while (resultSet.next()){
    10. //获取数据
    11. //获取该行第一列的字段值为int类型的元素
    12. System.out.println(resultSet.getInt(1));
    13. //获取该行第二列字段值为String类型的元素
    14. System.out.println(resultSet.getString(2));
    15. //获取该行第三列字段值为任意类型的元素
    16. System.out.println(resultSet.getObject(3));
    17. //获取该行字段名为entrydate对应的字段值
    18. System.out.println(resultSet.getObject("entrydate"));
    19. }
    20. statement.close();
    21. connection.close();
    22. }

    sql注入

    sql注入:通过操作输入来修改事先定义好的sql语句,用来达到执行代码对服务器进行攻击的方法

    sql注入测试用例-user表

    1. public static void main(String[] args) throws Exception {
    2. Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","root");
    3. System.out.println("请输入您的姓名:");
    4. String u = new Scanner(System.in).nextLine();
    5. System.out.println("请输入您的密码");
    6. String p = new Scanner(System.in).nextLine();
    7. //select * from user where username="lili" and password=123;因为username字段为varchar类型,需加双引号,password为int类型不需要加双引号(当然加了也可以)
    8. String sql="select * from user where username='"+u+"'and password="+p;
    9. Statement statement = connection.createStatement();
    10. ResultSet resultSet = statement.executeQuery(sql);
    11. //只要resultSet里面有数据就成功
    12. if(resultSet.next()){
    13. System.out.println("登录成功");
    14. }else {
    15. System.out.println("登录失败");
    16. }
    17. statement.close();
    18. connection.close();
    19. }

    验证sql注入:在输入姓名的后面直接写“lili'#”将后面的密码部分注释了进而登录成功

    PreparedStatement

    作用:预编译sql语句并执行,预防sql注入问题

    使用

    获取PreparedStatement对象:

    String sql="select * from where username=? and password=?"

    PreparedStatement p=connection.prepareStatement(sql);

    注意:以上sql为sql骨架,里面的?为占位符

    设置参数值

    给?赋值:p.setXxx(参数1,参数2);

    xxx:代表该字段值的数据类型(用Object覆盖所有类型)

    参数

    • 参数1:?的位置编号(从1开始)
    • 参数2:对应?的值

    执行sql

    executeUpdate();/executeQuery();

    注意:此次执行不需要再次传递sql

    解决sql注入

    1. public static void main(String[] args) throws Exception {
    2. Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/db","root","root");
    3. System.out.println("请输入您的姓名:");
    4. String u = new Scanner(System.in).nextLine();
    5. System.out.println("请输入您的密码");
    6. String p = new Scanner(System.in).nextLine();
    7. //预防sql注入
    8. String sql="select * from user where username=? and password=?";
    9. PreparedStatement preparedStatement = connection.prepareStatement(sql);
    10. preparedStatement.setString(1,u);
    11. //用object代表所有类型
    12. preparedStatement.setObject(2,p);
    13. ResultSet resultSet = preparedStatement.executeQuery();
    14. if(resultSet.next()){
    15. System.out.println("登录成功");
    16. }else {
    17. System.out.println("登录失败");
    18. }
    19. preparedStatement.close();
    20. connection.close();
    21. }

    注意:PreparedStatement本质上是把sql骨架和sql参数分开执行,遇到了#只是当作一个普通文本而不是注释符号了(将敏感字符进行转义)

    PreparedStatement好处

    • 预编译sql,性能更高
    • 防止sql注入:将敏感字符进行转义 

    注意:

    • PreparedStatement的预编译功能默认是关闭的 
    • 开启预编译功能:useServerPrepStmts=true(加到url?后面)

    如何理解预编译

    1. 首先来说statement,就是我们写好的sql发给mysql服务器,服务器进行sql语法检查,sql编译(编译成可执行的函数),后执行sql语句。
    2. 对于PreparedStatement来说,他会先检查sql骨架的语法,检查完后编译,将来我们设置完值的时候就可以直接执行

    数据库连接池

    简介

    • 数据库连接池是一个容器,负责分配,管理数据库连接
    • 他允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个
    • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏

    好处:

    • 资源重用
    • 提升系统响应速度
    • 避免数据库连接遗漏 

    不使用数据库连接池

    有很多用户访问这个数据库,来个用户就会现给他开一个数据库连接为该用户服务,服务结束后,连接关闭,再来一个用户再开一个连接为其服务,服务完关闭连接,循环往复,但是:开启数据库连接是一个非常耗时的工作(开启数据库连接就必须建立系统底层的资源,耗时间)而且用完之后关闭连接,关闭连接也耗费资源,不能做到资源的复用

    使用数据库连接池

    在系统启动之前初始化一个容器,然后在容器里面提前申请许多数据库连接(连接提前创建好)创建好之后将来有用户访问这个数据库,那么就会先从容器里面取出一个数据库连接给该用户使用,用户用完该连接,那么该连接会归还到数据库连接池容器里

    连接池的连接实现

    标准接口:DataSource

    官方sun提供的数据库连接池标准接口,由第三方组织实现此接口

    功能:获取连接=>Connection getConnection()

    注意:每一个数据库连接池中都有这样一个方法,继承自DataSource接口,用来获取连接对象

    常见的数据库连接池

    1. DBCP
    2. C3P0
    3. Druid

    Druid(德鲁伊)

    • 德鲁伊连接池是阿里巴巴开源的数据库连接池项目
    • 功能强大,性能优秀,是java语言最好的数据库连接池之一

    Driud使用步骤

    • 导入jar包-druid-1.1.12.jar
    • 定义配置文件
    • 加载配置文件
    • 获取数据库连接池对象
    • 获取连接

    配置文件

    1. #项目的src目录下放该druid.properties文件
    2. driverClassName=com.mysql.jdbc.Driver
    3. url=jdbc:mysql:///db?useSSL=false&userServerPrepStmts=true
    4. username=root
    5. password=root
    6. #初始化配置
    7. initialSize=5
    8. #最大连接数
    9. maxActive=10
    10. #最大等待时间——ms
    11. maxWait=3000

    表用例-emp

     

    1. public class DruidDemo {
    2. public static void main(String[] args) throws Exception {
    3. //加载配置文件
    4. Properties prop=new Properties();
    5. prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));
    6. //获取连接池对象——里面的参数为prop对象
    7. DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
    8. //获取对应的数据库连接
    9. Connection connection = dataSource.getConnection();
    10. String name="金庸";
    11. Integer age=43;
    12. String sql="select * from emp where name=? or age=?";
    13. PreparedStatement preparedStatement = connection.prepareStatement(sql);
    14. preparedStatement.setObject(1, name);
    15. preparedStatement.setObject(2, age);
    16. ResultSet resultSet = preparedStatement.executeQuery();
    17. while (resultSet.next()){
    18. //这里的i表示该行的列数
    19. for (int i=1;i<9;i++){
    20. System.out.println(resultSet.getObject(i));;
    21. }
    22. }
    23. }
    24. }

  • 相关阅读:
    hash:哈希表 哈希桶
    jQuery成功之路——jQuery动画效果和遍历效果概述
    概率密度函数,概率分布函数
    关于HarmonyOS元服务的主题演讲与合作签约
    项目实战总结
    【web后端】C#类与继承、随机数写法、虚函数、例题
    Linux之安全最佳做法(未完成)
    外卖项目(SpringBoot)--- 数据表设计、创建项目工程、登录模块
    [激光原理与应用-109]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 12 - 焊接工艺之影响焊接效果的因素
    渗透测试-命令执行漏洞
  • 原文地址:https://blog.csdn.net/m0_60027772/article/details/125988429