JDBC操作数据库

一、简介

1.概述

JDBC使用Java语言操作不同的关系型数据库的一套API(标准接口)
Java DataBase Connectivity )Java数据库连接

2.好处

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

3.驱动

JDBC驱动由数据库厂商提供

  1. 在个人开发与测试中,可以使用JDBC-ODBC桥连方式

    • 将对JDBC API的调用,转换为对另一组数据库连接API的调用
    • 优点:可以访问所有ODBC可以访问的数据库
    • 缺点:执行效率低、功能不够强大
  2. 在生产型开发中,推荐使用纯Java驱动方式

    • 由JDBC驱动直接访问数据库
    • 优点:完全Java代码,快速、跨平台
    • 缺点:访问不同的数据库需要下载专用的JDBC驱动

二、步骤

0.创建工程,导入驱动jar包
(1)导入jar后需要add as library
(2)创建Java实现类Class
 1. 加载数据库驱动程序:
   Class.forName("com.mysql.jdbc.Driver"); // 加载MySQL驱动程序
2. 建立数据库连接:
   String url = "jdbc:mysql://localhost:3306/mydatabase";
   String username = "username";
   String password = "password";
   Connection connection = 
   DriverManager.getConnection(url, username, password);    
3. 创建Statement对象:
   Statement statement = connection.createStatement();   
4. 执行SQL查询语句:
   String sql = "SELECT * FROM customers";
     // 执行查询语句并返回结果集
   ResultSet resultSet = statement.executeQuery(sql); 
   // 遍历结果集
   while (resultSet.next()) {
       String name = resultSet.getString("name");
       int age = resultSet.getInt("age");
       System.out.println("Name: " + name + ", Age: " + age);
   }
5. 执行SQL更新语句:
   String sql = "UPDATE customers SET age = 25 WHERE id = 1";
   // 执行更新语句并返回受影响的行数
   int rowsAffected = statement.executeUpdate(sql); 
6. 关闭连接和相关资源:
    if(resultSet!=null)
   resultSet.close();
   if(statement!=null)
   statement.close();
   if(connection!=null)
   connection.close();

释放资源是为了优化系统的性能和效率,好处:

  1. 节省内存:释放不再使用的资源可以释放占用的内存空间,提高系统的可用内存,从而使其他应用程序可以更快速地执行。
  2. 避免内存泄漏:释放资源可以防止内存泄漏的问题。内存泄漏是指程序中分配的内存空间在不再使用时没有被释放,导致内存占用不断增加,严重时可能导致系统崩溃。
  3. 提高系统稳定性:释放资源可以减少系统负载和内存使用量,从而提高系统的稳定性和可靠性。避免资源过度占用也可以降低系统崩溃的风险。
  4. 提升用户体验:释放资源可以加快应用程序的响应速度,减少卡顿和延迟现象,提升用户的使用体验。

三、API详解

API解释

[API 是 “Application Programming Interface” 的缩写,指的是应用程序编程接口。它是一组定义了软件组件如何相互通信和交互的规范。
API 允许不同的软件系统之间进行交互,并共享数据和功能。通过使用 API,开发人员可以直接访问其他软件或服务的功能,而无需了解其内部工作原理]

JDBC API

JDBC API主要功能:与数据库建立连接、执行SQL语句、处理结果
在这里插入图片描述

  • DriverManager:依据数据库的不同,管理JDBC驱动
  • Connection:负责连接数据库并担任传送数据的任务
  • Statement:由 Connection产生、负责执行SQL语句
  • ResultSet:负责保存Statement执行后所产生的查询结果

驱动管理类DriverManager作用

1.注册驱动(反射原理)
[将一个类加载到内存],抛出异常,[在mysql5后可省略]
Class.forName("com.mysql.jdbc.Driver");
在使用 JDBC 连接 MySQL 数据库之前,需要确保 MySQL JDBC 驱动程序已经被加载。通过调用 `Class.forName()` 方法,并传递驱动程序的完整类名 `"com.mysql.jdbc.Driver"`,可以动态加载该驱动程序的类,并注册到 Java 的 `DriverManager` 中。
`com.mysql.jdbc.Driver` 是旧版本 MySQL JDBC 驱动程序的包名。
如果使用的是 MySQL Connector/J 8.0 或更新版本,应该使用 `com.mysql.cj.jdbc.Driver`。
在Java 6及更高版本中,JDBC驱动程序的自动加载已经被引入,因此不再需要显式调用 `Class.forName()` 来加载驱动程序。只需要在连接数据库之前,确保相应的驱动程序 JAR 文件已经被添加到类路径即可。例如:
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/mydatabase", "username", "password");
这将自动扫描类路径上可用的驱动程序,并注册与数据库 URL 匹配的驱动程序,无需显式加载驱动程序类。

Driver类的静态方法,加载自动执行
registerDriver(Driver,driver)使用DriverManager注册给定的驱动程序
在这里插入图片描述

在mysql5.5之后,自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动
在这里插入图片描述

2.获取连接
String url="jdbc:mysql://ip端口/需要连接的数据库?参数键值对"
String username="";
String password="";
Connection conn =DriverManager.getConnection(url,username,password);

url连接路径

jdbc连接MySQL的协议---jdbc:mysql:// 
需要连接的数据库地址---ip地址(域名):端口号/
需要连接的数据库---数据库名称?参数键值对1&参数键值对2...

例如
jdbc:mysql://ip地址:端口号/数据库名称?serverTimezone=Asia/Shanghai&characterEncording=utf-8

如果连接的是本机MySQL服务器,并且MySQL服务默认端口是3306
url简写jdbc:mysql:///数据库名称?参数键值对1...

数据库连接对象Connection作用

1.获取执行SQL对象
//普通执行SQL对象
Statement            createStatement();

//预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement     preparedStatement(sql);

//执行存储过程的对象[不常使用]
CallableStatement     prepareCall(sql);

(事务管理)
MySQL事务管理

开启事务:begin;/start transaction;
提交事务:commit;
回滚事务:rollback;
MySQL默认自动提交事务

JDBC事务管理

开启事务:setAutoCommit(boolean autoCommit):
true自动提交事务,false为手动提交事务
提交事务:commit()
回滚事务:rollback()
2.事务管理版
Statement stmt =conn.createStatement();
//如果在多个执行sql语句时发现异常,需要回滚
try{
    //开启事务
    conn.setAutoCommit(false);
    
    int count=stmt.executeUpadte(sql);
    Sysytem.out.print(count);
    
    //提交事务
    conn.commit();
}catch(Exception e){
    //回滚事务
    conn.rollback();
    e.printStackTrace();
}

Statement作用

在这里插入图片描述

1.执行sql语句,处理结果
//执行DML增删改、DDL对表和库的增删改查语句
//返回值(1)DML语句影响的行数(2)DDL语句执行后,执行成功也可能返回0
int count=stmt.executeUpadte(sql);

结果集对象ResultSet作用

在这里插入图片描述

1.封装DQL查询语句的结果
2.获取查询结果
next(): 光标向下移动一行,并且判断当前行是否为有效行
返回值 true有效行,当前行有数据;false无效行,当前行没有数据

get数据类型():获取数据
int getInt(参数);
String getString(参数);
参数int :列的编号,从1开始
参数String :列的名称

例:

//执行DQL查询语句,返回ResultSet对象
ResultSet rs=stmt.executeQuery(sql);
//遍历结果集
while(rs.next()){
    int a=rs.getInt(1);
    int b=rs.getInt("id");
}

PreparedStatement作用

1.预编译SQL的执行SQL对象:防止SQL注入
SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法,如: ‘or’1’='1

1.步骤
①获取preparedStatement对象
//SQL语句中的参数值,使用占位符?替代
String sql="select * from user where username =? and password =?";
//通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt =conn.prepareStatement(sql);
②设置参数值
PreparedStatement对象,setXxx(参数1,参数2):?赋值
?的位置编号从1开始
③执行SQL语句
executeUpdate();executeQuery();//不需要再传递sql
2.好处

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

3.原理

①在获取PreparedStatement对象时,将SQL语句发送给mysql服务器
进行检查,编译(耗时)
②执行时就不用再进行这些步骤了,速度很快
③如果SQL模板一样,则只需要进行一次检查、编译
在这里插入图片描述

4.开启功能及展示日志

开启PreparedStatement预编译功能

String url="...参数键值对 & useServerPrepStmts=true ";

配置MySQL执行日志my.imi(重启mysql服务后生效)

log-output=FILE
general-log=1
general_log_file="D:\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2

四、JDBC预编译功能代码

public class BaseDao {
    //4个属性
    //驱动地址
    public static final String DRIVER="com.mysql.cj.jdbc.Driver";
    //连接地址
    public static final String URL="jdbc:mysql://localhost:3306/数据库名?serverTimezone=Asia/Shanghai";
    //用户名
    public static final String USER="root";
    //密码
    public static final String PASSWORD="ok";
    //3个对象
    //连接对象
    public static Connection conn;
    //预编译对象
    public static PreparedStatement ppst;
    //结果集对象
    public static ResultSet rs;
    //1个静态方法块
    //加载驱动
    static {
        try {
            Class.forName(DRIVER);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
            }
    }

    //4个方法
    //获取连接方法
    public static void getConnection(){
        try {
            //当没有连接或者连接被关闭的时候
            if (conn==null||conn.isClosed())
                conn= DriverManager.getConnection(URL, USER,PASSWORD);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    //释放资源方法
    public static void closeAll(){
        try {
            if (rs!=null)rs.close();
            if (ppst!=null)ppst.close();
            if (conn!=null)conn.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 通用增删改方法
     * @param sql 输入的sql语句
     * @param o 可变参数
     */
    public static int excuteUpdate(String sql, Object...o){
        //声明返回结果
        int result=0;
        //获取连接对象
        getConnection();
        try {
            //通过conn获取ppst对象。并对sql进行预编译
            ppst= conn.prepareStatement(sql);
            //循环遍历可变参数(当成数组来用)
            for (int i = 0; i < o.length; i++) {
                ppst.setObject((i+1),o[i]);
            }
            //执行sql语句,返回受影响的行数
            result=ppst.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //关闭资源
            closeAll();
        }
        return result;
    }

    /**
     * 通用查询方法
     * @param sql 输入的sql语句
     * @param o 可变参数
     */
    public static void excuteQuery(String sql, Object...o){
        //获取连接对象
        getConnection();
        try {
            //通过conn获取ppst对象。并对sql进行预编译
            ppst= conn.prepareStatement(sql);
            //循环遍历可变参数(当成数组来用)
            for (int i = 0; i < o.length; i++) {
                ppst.setObject((i+1),o[i]);
            }
            //执行sql语句,返回受影响的行数
            rs=ppst.executeQuery();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值