文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Java数据库连接(JDBC)

2023-09-22 20:29

关注

JDBC(Java DataBase Connectivity)

JDBC概念

JDBC   就是使用Java语言操作关系型数据库的一套API全称:( Java DataBase Connectivity ) Java 数据库连接

JDBC本质

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

JDBC好处

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

在这里插入图片描述

JDBC快速入门

Java操作数据库流程

第一步:编写Java代码第二步:Java代码将SQL发送到MySQL服务端第三步:MySQL服务端接收到SQL语句并执行该SQL语句第四步:将SQL语句执行的结果返回给Java代码

编写代码具体步骤

创建工程,导入jar包

1.创建新的空的项目2.定义项目的名称,并指定位置3.对项目进行设置,JDK版本、编译版本4.创建模块,指定模块的名称及位置5.导入驱动包,将mysql的驱动包放在模块下的lib目录(随意命名)下,并将该jar包添加为库文件在添加为库文件的时候,有如下三个选项Global Library  : 全局有效       Project Library :   项目有效    Module Library : 模块有效    6.在src下创建类

编写代码

public class JDBCDemo {    public static void main(String[] args) throws Exception {        //1. 注册驱动        Class.forName("com.mysql.jdbc.Driver");        //2. 获取连接        String url = "jdbc:mysql://127.0.0.1:3306/db1";        String username = "root";        String password = "1234";        Connection conn = DriverManager.getConnection(url, username, password);        //3. 定义sql        String sql = "update account set money = 2000 where id = 1";        //4. 获取执行sql的对象 Statement        Statement stmt = conn.createStatement();        //5. 执行sql        int count = stmt.executeUpdate(sql);//受影响的行数        //6. 处理结果        System.out.println(count);        //7. 释放资源        stmt.close();        conn.close();    }}

API详解

DriverManager

作用:1.注册驱动     Class.forName("com.mysql.jdbc.Driver");        MySQL 5之后的驱动包,可以省略注册驱动的步骤,自动加载jar包中的META-INF/services/java.sql.Driver文件中的驱动类              2.获取数据库连接   static Connection     getConnection(String url,String user,String password)        参数:url:连接路径             语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…              细节:1. 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对       2.配置 useSSL=false 参数,禁用安全连接方式,解决警告提示

Connection

作用:1.获取执行SQL的对象     * 普通执行SQL对象  Statement createStatement()    * 预编译SQL的执行SQL对象:防止SQL注入   PreparedStatement  prepareStatement(sql)        * 执行存储过程的对象  CallableStatement prepareCall(sql)      2.管理事务,Connection接口中定义了3个对应的方法      开启事务:setAutoCommit(boolean autoCommit):true:自动提交事务;false:手动提交事务,即为开启事务      提交事务:commit()      回滚事务:rollback()
public class JDBCDemo3_Connection {    public static void main(String[] args) throws Exception {        //1. 注册驱动        //Class.forName("com.mysql.jdbc.Driver");        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写        String url = "jdbc:mysql:///db1?useSSL=false";        String username = "root";        String password = "1234";        Connection conn = DriverManager.getConnection(url, username, password);        //3. 定义sql        String sql1 = "update account set money = 3000 where id = 1";        String sql2 = "update account set money = 3000 where id = 2";        //4. 获取执行sql的对象 Statement        Statement stmt = conn.createStatement();        try {            // ============开启事务==========            conn.setAutoCommit(false);            //5. 执行sql            int count1 = stmt.executeUpdate(sql1);//受影响的行数            //6. 处理结果            System.out.println(count1);            int i = 3/0;            //5. 执行sql            int count2 = stmt.executeUpdate(sql2);//受影响的行数            //6. 处理结果            System.out.println(count2);            // ============提交事务==========            //程序运行到此处,说明没有出现任何问题,则需求提交事务            conn.commit();        } catch (Exception e) {            // ============回滚事务==========            //程序在出现异常时会执行到这个地方,此时就需要回滚事务            conn.rollback();            e.printStackTrace();        }        //7. 释放资源        stmt.close();        conn.close();    }}

Statement

作用:执行SQL语句  int executeUpdate(sql):执行DML、DDL语句  返回值:(1)DML语句影响的行数      (2)DDL语句执行后,执行成功也可能返回0  ResultSet  executeQuery(sql):执行DQL语句  返回值:ResultSet结果集对象
@Testpublic void testDML() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);    //3. 定义sql    String sql = "update account set money = 3000 where id = 1";    //4. 获取执行sql的对象 Statement    Statement stmt = conn.createStatement();    //5. 执行sql    int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数    //6. 处理结果    //System.out.println(count);    if(count > 0){        System.out.println("修改成功~");    }else{        System.out.println("修改失败~");    }    //7. 释放资源    stmt.close();    conn.close();}
@Testpublic void testDDL() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);    //3. 定义sql    String sql = "drop database db2";    //4. 获取执行sql的对象 Statement    Statement stmt = conn.createStatement();    //5. 执行sql    int count = stmt.executeUpdate(sql);//执行完DDL语句,可能是0    //6. 处理结果    System.out.println(count);    //7. 释放资源    stmt.close();    conn.close();}

ResultSet(结果集对象)

作用:封装DQL查询语句结果ResultSet stmt.executeQuery(sql) 执行DQL语句,返回ResultSet对象*获取查询结果boolean next():1.将光标从当前位置向前移动一行  2.判断当前行是否是有效行返回值:true:有效行,当前行有数据  false:无效行,当前行没有数据xxx getXxx(参数):获取数据xxx:数据类型;比如:int getInt(参数);String getString(参数)参数:*int:列的编号,从1开始*String:列的名称*使用步骤(1)游标向下移动一行,并判断该行是否有数据:next()(2)获取数据:getXxx(参数)
 while(rs.next()){            int id = rs.getInt(1);            String name = rs.getString(2);            System.out.println(id);            System.out.println(name);           }
案例
需求:查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中

实体类Account

package com.zyl.pojo;public class Account {    private int id;    private String name;    private double money;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public double getMoney() {        return money;    }    public void setMoney(double money) {        this.money = money;    }    @Override    public String toString() {        return "Account{" +                "id=" + id +                ", name='" + name + '\'' +                ", money=" + money +                '}';    }}
@Testpublic void testResultSet2() throws  Exception {    //1. 注册驱动    //Class.forName("com.mysql.jdbc.Driver");    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);    //3. 定义sql    String sql = "select * from account";    //4. 获取statement对象    Statement stmt = conn.createStatement();    //5. 执行sql    ResultSet rs = stmt.executeQuery(sql);    // 创建集合    List<Account> list = new ArrayList<>();       // 6.1 光标向下移动一行,并且判断当前行是否有数据    while (rs.next()){        Account account = new Account();        //6.2 获取数据  getXxx()        int id = rs.getInt("id");        String name = rs.getString("name");        double money = rs.getDouble("money");        //赋值        account.setId(id);        account.setName(name);        account.setMoney(money);        // 存入集合        list.add(account);    }    System.out.println(list);    //7. 释放资源    rs.close();    stmt.close();    conn.close();}

PreparedStatement

作用:预编译SQL语句并执行:预防SQL注入问题*SQL注入:通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法

演示SQL注入

@Testpublic void testLogin() throws  Exception {    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);    // 接收用户输入 用户名和密码    String name = "sjdljfld";    String pwd = "' or '1' = '1";    String sql = "select * from tb_user where username = '"+name+"' and password = '"+pwd+"'";    // 获取stmt对象    Statement stmt = conn.createStatement();    // 执行sql    ResultSet rs = stmt.executeQuery(sql);    // 判断登录是否成功    if(rs.next()){        System.out.println("登录成功~");    }else{        System.out.println("登录失败~");    }    //7. 释放资源    rs.close();    stmt.close();    conn.close();}

防止SQL注入 PrepareStatement

1. 获取 PreparedStatement 对象
// SQL语句中的参数值,使用?占位符替代String sql = "select * from user where username = ? and password = ?";// 通过Connection对象获取,并传入对应的sql语句PreparedStatement pstmt = conn.prepareStatement(sql);
2.设置参数值  上面的sql语句中参数使用 ? 进行占位,在之前之前肯定要设置这些 ?  的值。  PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值   * Xxx:数据类型 ; 如 setInt (参数1,参数2)   * 参数:     * 参数1: ?的位置编号,从1 开始         * 参数2: ?的值3. 执行SQL语句   executeUpdate();  执行DDL语句和DML语句   executeQuery();  执行DQL语句   注意:  * 调用这两个方法时不需要传递SQL语句,因为获取SQL语句执行对象时已经对SQL语句进行预编译了。
 @Testpublic void testPreparedStatement() throws  Exception {    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写    String url = "jdbc:mysql:///db1?useSSL=false";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);    // 接收用户输入 用户名和密码    String name = "zhangsan";    String pwd = "' or '1' = '1";    // 定义sql    String sql = "select * from tb_user where username = ? and password = ?";    // 获取pstmt对象    PreparedStatement pstmt = conn.prepareStatement(sql);    // 设置?的值    pstmt.setString(1,name);    pstmt.setString(2,pwd);    // 执行sql    ResultSet rs = pstmt.executeQuery();    // 判断登录是否成功    if(rs.next()){        System.out.println("登录成功~");    }else{        System.out.println("登录失败~");    }    //7. 释放资源    rs.close();    pstmt.close();    conn.close();}

PrepareStatement原理

PreparedStatement 好处:* 预编译SQL,性能更高* 防止SQL注入:将敏感字符进行转义

Java代码操作数据库流程:1.将sql语句发送到MySQL服务器端2.MySQL服务端会对sql语句进行如下操作3. 检查SQL语句    检查SQL语句的语法是否正确。4.编译SQL语句。将SQL语句编译成可执行的函数。检查SQL和编译SQL花费的时间比执行SQL的时间还要长。如果我们只是重新设置参数,那么检查SQL语句和编译SQL语句将不需要重复执行。这样就提高了性能。 5. 执行SQL语句

演示PrepareStatement原理

1.开启预编译功能在代码中编写url时需要加上以下参数。而我们之前根本就没有开启预编译功能,只是解决了SQL注入漏洞。useServerPrepStmts=true2.配置MySQL执行日志(重启mysql服务后生效)在mysql配置文件(my.ini)中添加如下配置:log-output=FILEgeneral-log=1general_log_file="D:\mysql.log"slow-query-log=1slow_query_log_file="D:\mysql_slow.log"long_query_time=23.java测试代码如下:
@Testpublic void testPreparedStatement2() throws  Exception {    //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写    // useServerPrepStmts=true 参数开启预编译功能    String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true";    String username = "root";    String password = "1234";    Connection conn = DriverManager.getConnection(url, username, password);    // 接收用户输入 用户名和密码    String name = "zhangsan";    String pwd = "' or '1' = '1";    // 定义sql    String sql = "select * from tb_user where username = ? and password = ?";    // 获取pstmt对象    PreparedStatement pstmt = conn.prepareStatement(sql);    Thread.sleep(10000);    // 设置?的值    pstmt.setString(1,name);    pstmt.setString(2,pwd);    ResultSet rs = null;    // 执行sql    rs = pstmt.executeQuery();    // 设置?的值    pstmt.setString(1,"aaa");    pstmt.setString(2,"bbb");    // 执行sql    rs = pstmt.executeQuery();    // 判断登录是否成功    if(rs.next()){        System.out.println("登录成功~");    }else{        System.out.println("登录失败~");    }    //7. 释放资源    rs.close();    pstmt.close();    conn.close();}
4.执行SQL语句,查看 `D:\mysql.log` 日志==小结:==* 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)* 执行时就不用再进行这些步骤了,速度更快* 如果sql模板一样,则只需要进行一次检查、编译

数据库连接池

简介

1. 数据库连接池是个容器,负责分配、管理数据库连接(Connection)2.它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;3. 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏* 好处  * 资源重用  * 提升系统响应速度  * 避免数据库连接遗漏  连接池是在一开始就创建好了一些连接(Connection)对象存储起来。用户需要连接数据库时, 不需要自己创建连接,而只需要从连接池中获取一个连接进行使用,使用完毕后再将连接对象归还给连接池; 这样就可以起到资源重用,也节省了频繁创建连接销毁连接所花费的时间,从而提升了系统响应的速度。

实现

 * 标准接口:DataSource  官方(SUN) 提供的数据库连接池标准接口,由第三方组织实现此接口。该接口提供了获取连接的功能: Connection getConnection()那么以后就不需要通过 `DriverManager` 对象获取 `Connection` 对象,而是通过连接池(DataSource)获取 `Connection` 对象。* 常见的数据库连接池 * DBCP * C3P0 * Druid * Druid(德鲁伊)  * Druid连接池是阿里巴巴开源的数据库连接池项目   * 功能强大,性能优秀,是Java语言最好的数据库连接池之一

使用

1.导入jar包 druid-1.1.12.jar先将druid的jar包放到项目下的lib下并添加为库文件2. 定义配置文件配置文件 druid.properties放在src目录下driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=trueusername=rootpassword=1234# 初始化连接数量initialSize=5# 最大连接数maxActive=10# 最大等待时间maxWait=30003.加载配置文件4.获取数据库连接池对象5.获取连接

具体实现:

public class DruidDemo {    public static void main(String[] args) throws Exception {        //1.导入jar包        //2.定义配置文件        //3. 加载配置文件        Properties prop = new Properties();        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));        //4. 获取连接池对象        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);        //5. 获取数据库连接 Connection        Connection connection = dataSource.getConnection();        System.out.println(connection); //获取到了连接后就可以继续做其他操作了        //System.out.println(System.getProperty("user.dir"));    }}

来源地址:https://blog.csdn.net/qq_47446178/article/details/129369898

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯