day23_jdbc详解

JDBC

JDBC概述

什么jdbc

Java DataBase Connectivity是一种用于执行SQL语句的Java API,它由一组用Java语言编写的类和接口组成。通过这些类和接口,JDBC把SQL语句发送给不同类型的数据库进行处理并接收处理结果。

jdbc的作用

提供java 操作不同数据库的技术

JDBC两大类

对Java开发人员而言是API,对数据库提供商而言是接口。

面向开发人员:作为API,JDBC为程序开发提供标准的接口。

面向数据库厂商:作为接口,让数据库厂商按标准方法来实现数据库连接与操作(数据库驱动程序)。

在这里插入图片描述

JDBC工作过程

在这里插入图片描述

Jdbc数据库连接

1.下载Jar
官网连接
(注意与自的mysql版本匹配哦)随便选择一个下载
在这里插入图片描述

2.引入Jar (包括jdbc 驱动程序 )

  1. JDBC 使用步骤

    ​ 1. 加载驱动 (只会运行一次:static)

    ​ 2. 获得链接对象 Connection

    ​ 3. 获得执行对象 Statement

    ​ 4. 执行sql并获得结果集(ResultSet)

    ​ 5. 处理结果集

    1. 释放资源
    public static void main(String[] args) throws SQLException {
        //1.注册驱动 告诉jdbc我们使用哪一个数据库厂商的驱动
        //驱动管理器专门注册驱动(需要传递一个驱动对象)
        // DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Class.forName("com.mysql.jdbc.Driver");
        //2. 建立驱动连接
        //url:链接数据库的地址  jdbc:mysql://localhost:3306/数据库的名字
        //user:用户名
        //password:密码
        //面向接口编程
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");
    
        //3.创建向数据库发送sql的statement对象
        Statement st = connection.createStatement();
    
        //4.发送sql后获得一个封装了查询结果的ResultSet对象
        ResultSet rs = st.executeQuery("select * from student limit 1");
    
        //5.解析ResultSet对象获得结果
    
        if(rs.next()) {
    
            System.out.println("id:"+rs.getObject("Id"));
            System.out.println("name:"+rs.getObject("StudentName"));       System.out.println("age:"+rs.getObject("age"));
        }
        //释放资源
        rs.close();
        st.close();
        connection.close();
    }
    

2.Api详解

2.1 注册驱动

DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用

原因有2个:

>导致驱动被注册2次。

>强烈依赖数据库的驱动jar

解决办法:

注册驱动的第二种方式

Class.forName(“com.mysql.jdbc.Driver”);

2.2 获取链接

static Connection getConnection(String url, String user, String password)

试图建立到给定数据库 URL 的连接。

参数说明:url 需要连接数据库的位置(网址) user用户名 password 密码

例如:getConnection(“jdbc:mysql://localhost:3306/数据库名称”, “root”, “”);

URL:SUN公司与数据库厂商之间的一种协议。

jdbc:mysql://localhost:3306/数据库名称

协议 子协议 IP : 端口号 数据库

常用数据库URL地址的写法: 
Oracle写法:jdbc:oracle:thin:@localhost:1521:sid 
SqlServer jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid 
MySql jdbc:mysql://localhost:3306/sid 
Mysql的url地址的简写形式: jdbc:mysql:///sid 
常用属性:useUnicode=true&characterEncoding=UTF-8

接口的实现在数据库驱动中。所有与数据库交互都是基于连接对象的。

Statement createStatement(); //创建操作sql语句的对象

2.3 API详解:java.sql.Statement接口: 操作sql语句,并返回相应结果

String sql = “某SQL语句”;

获取Statement语句执行平台:Statement stmt = con.createStatement();

常用方法:

int executeUpdate(String sql); --执行insert update delete语句.

ResultSet executeQuery(String sql); --执行select语句.

boolean execute(String sql); --仅当执行select并且有结果时才返回true,执行其他的语句返回false.

 //1.注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		
		//2.获取链接
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","root");
		
		
		//3.获取代表向数据库发送sql的statement对象
		Statement st = conn.createStatement();
		
		String sql="insert into student(name,age) values('奥利给','20')";
		
		//4.发送sql
		//返回影响的行数 大于0代表执行成功
		int result = st.executeUpdate(sql);
		
		if(result>0) {
			System.out.println("插入成功");
		}
		
		//5.释放资源
		st.close();
		conn.close();

2.4 API详解:处理结果集(注:执行insert、update、delete无需处理)

ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法

时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1

开始)来获取指定列的数据:

rs.next();//指向第下一行

rs.getObject(1);//获取第一行第一列的数据

在这里插入图片描述

常用方法:

n Object getObject(int index) / Object getObject(String name) 获得任意对象

n String getString(int index)/ String getString(String name) 获得字符串

n int getInt(int index)/int getInt(String name) 获得整形

n double getDouble(int index)/ double getDouble(String name) 获得双精度浮点型

在这里插入图片描述

2.5 释放资源

与IO流一样,使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。

rs.close(); //结果集

stmt.close(); //statement对象

con.close(); //连接对象

2.6 关闭异常处理

public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取链接
        Connection conn =null;
        Statement st=null;
        ResultSet rs=null;
        try {
        //2.获取链接
         conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc","root","root");
        //3.获取代表向数据库发送sql的statement对象
         st = conn.createStatement();
        String sql="select id,name,age from student";
        //4.发送sql
        rs = st.executeQuery(sql);
        //定义集合封装Student数据
        List<Student> list=new ArrayList<Student>();
        while(rs.next()) {
            //查询出来的结果封装到对象中
            Student s=new Student();
            s.setId(rs.getInt("id"));
            s.setAge(rs.getInt("age"));
            s.setName(rs.getString("name"));
            list.add(s);
        }
        System.out.println(list);
        }finally {
            //5.释放资源
            //关闭资源之前一定要判断
            if(rs!=null) {
                try {
                   rs.close();
                }catch (Exception e) {
                    e.printStackTrace();
                }
                //让jvm回收没有被关闭的rs对象
                rs=null;
            }
            if(st!=null) {
                try {
                st.close();
            
                }catch (Exception e) {
                    e.printStackTrace();
                }
                st=null;
            }
            if(conn!=null) {
                try {
                    conn.close();
                }catch (Exception e) {
                    e.printStackTrace();
                }
                conn=null;
            } 
        }
    }
}

封装JDBC(重点)

  1. 提交公共方法(获取连接,释放资源)

  2. 将这两方法,提到一个类中 JdbcUtils

  3. 将数据库连接url, 用户名,密码,放到文件中,把它变成可以配置的

步骤1,步骤2:

public class JdbcUtils {
    static {
        //1.注册驱动  告诉jdbc我们使用哪一个数据库厂商的驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
    // 项目一旦交付
    // 公司(乙)  做项目(产品)  =》   给别人做项目(甲)
    //                                部署(运维)-》 配置文件
    public static Connection GetConnection() throws ClassNotFoundException, SQLException {
        //2.通过驱动管理器获取一个链接
        Connection connection = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/j352", "root", "");
        return  connection;
    }
    public static void release(Connection conn, Statement sm , ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs =null; //让jvm来回收它
        }
        if(sm!=null){
            try {
                sm.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            sm =null; //让jvm来回收它
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn =null; //让jvm来回收它
        }
    }
}

步骤3: 将数据库连接url, 用户名,密码,放到文件中,把它变成可以配置的

Properties

在这里插入图片描述

使用properties后的代码

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/j352
username=root
password=xxx
public class JdbcUtils {
    private static Properties properties = new Properties();
    static {
        //1.注册驱动  告诉jdbc我们使用哪一个数据库厂商的驱动
        try {
            //1.1 读取文件中的信息
            FileInputStream in = null;
            try {
                in = new FileInputStream("src/jdbc.properties");
            } catch (FileNotFoundException e) {
                throw new RuntimeException(e);
            }
            // 1.2  Properties对象中有一个load方法
            properties.load(in);  //将文件相关的信息加载到properties 对象中
            Class.forName(properties.getProperty("driverClassName"));
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    // 项目一旦交付
    // 公司(乙)  做项目(产品)  =》   给别人做项目(甲)
    //                                部署(运维)-》 配置文件
    public static Connection GetConnection() throws ClassNotFoundException, SQLException, IOException {
        // 读取文件中的数据 jdbc.properties ,进行使用

        //String getProperty(String key)
        //2.通过驱动管理器获取一个链接
        Connection connection = (Connection) DriverManager.getConnection(properties.getProperty("url"),
                                                                         properties.getProperty("username"), properties.getProperty("password"));
        return  connection;
    }
    public static void release(Connection conn, Statement sm , ResultSet rs){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs =null; //让jvm来回收它
        }
        if(sm!=null){
            try {
                sm.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            sm =null; //让jvm来回收它
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn =null; //让jvm来回收它
        }
    }
}

SQL注入(要知道详情可以百度)

案例:登录

如果执行的sql语句,是用字符串进行拼接, 就容易出sql 注入

在这里插入图片描述

如何防止sql注入

  1. 输入时,不让它输入特殊字符 ,正则表达式限定(只输入字母或数字 )

  2. 执行sql时不用sql拼接,而使用参数化查询

    public int login(String username, String pwd) {
            int result = 0;
            Connection conn = null; //创建连接
    //        Statement statement = null;
            PreparedStatement pst = null;
            ResultSet resultSet = null;
            try {
                conn = JdbcUtils.GetConnection();
    
                // 查询
                String sql = "select * from user where username=? and pwd=? ";
                pst = conn.prepareStatement(sql);
                pst.setString(1,username);
                pst.setString(2,pwd);
                System.out.println(sql);
    
                resultSet = pst.executeQuery(sql);
                if (resultSet.next()) {
                    result = 1;
                 }
    
    
                }  catch (ClassNotFoundException e) {
                   result = 2;
                   e.printStackTrace();
    //                throw new RuntimeException(e);
                } catch (SQLException e) {
                    result = 3;
                    e.printStackTrace();
                } catch (IOException e) {
                    result = 4;
                    e.printStackTrace();
                }finally {
                JdbcUtils.release(conn,pst,resultSet);
                }
    
            return  result;
        }
    

Jdbc控制事务

java中事务的控制

conn.setAutoCommit(false) == start transaction;

conn.commit() == commit;

conn.rollback(); == rollback;

public class TransactionDemo {
    public static void main(String[] args) {
        // 1. 获取连接
       Connection connection =  null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try{
            connection = JdbcUtils.GetConnection();
            //2. 事务开启
            connection.setAutoCommit(false);
            String sql = "update user set age = 18 where username='admin'";
            statement = connection.prepareStatement(sql);
            statement.executeUpdate(); //执行sql

//            int x= 1/ 0 ;

            String sql2 = "update user set age = 28 where username='doubleyong'";
            statement = connection.prepareStatement(sql2);
            statement.executeUpdate(); //执行sql
            // 3。提交事务
            connection.commit();

        }catch (Exception e){
            //关闭事务
            try {
                connection.rollback();
//                connection.commit();
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
            e.printStackTrace();
        }
        finally {
            JdbcUtils.release(connection,statement,resultSet);
        }
    }
}

事务的回滚点

回滚到指定位置

savepoint = conn.setSavepoint();

 public static void main(String[] args) {
        // 1. 获取连接
       Connection connection =  null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Savepoint savepoint=null;
        try{
            connection = JdbcUtils.GetConnection();
            //2. 事务开启
            connection.setAutoCommit(false);
            String sql = "update user set age = 66 where username='admin'";
            statement = connection.prepareStatement(sql);
            statement.executeUpdate(); //执行sql

            //设置一个事务的回滚点
            savepoint = connection.setSavepoint();
            int x= 1/ 0 ;

            String sql2 = "update user set age = 77 where username='doubleyong'";
            statement = connection.prepareStatement(sql2);
            statement.executeUpdate(); //执行sql
            // 3。提交事务
            connection.commit();

        }catch (Exception e){
            //关闭事务
            try {
                connection.rollback(savepoint); //回滚到指定事物点
                connection.commit(); //回滚后,如何 还是有sql执行,必须 加上commit 
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
            e.printStackTrace();
        }
        finally {
            JdbcUtils.release(connection,statement,resultSet);
        }
    }

= connection.prepareStatement(sql2);
statement.executeUpdate(); //执行sql
// 3。提交事务
connection.commit();

    }catch (Exception e){
        //关闭事务
        try {
            connection.rollback(savepoint); //回滚到指定事物点
            connection.commit(); //回滚后,如何 还是有sql执行,必须 加上commit 
        } catch (SQLException ex) {
            throw new RuntimeException(ex);
        }
        e.printStackTrace();
    }
    finally {
        JdbcUtils.release(connection,statement,resultSet);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/237781.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML面试题---专题一

文章目录 一、前言二、 HTML5 中 <header> 和 <footer> 标签的用途是什么&#xff1f;三、如何在 HTML 中嵌入 SVG&#xff08;可缩放矢量图形&#xff09;文件&#xff1f;四、解释 contenteditable 属性的用途五、如何创建随屏幕尺寸缩放的响应式图像&#xff1f…

虚幻学习笔记11—C++结构体、枚举与蓝图的通信

一、前言 结构体的定义和枚举类似&#xff0c;枚举的定义有两种方式。区别是结构体必须以“F”开头命名&#xff0c;而枚举不用。 额外再讲了一下蓝图生成时暴露变量的方法。 二、实现 2.1、结构体 1、定义结构体 代码如下&#xff0c;注意这个定义的代码一定要在“UCLASS()”…

如何将用户有过行为的item用list形式记录下来,另外如何计算list里的个数

导语&#xff1a; 最近做项目&#xff0c;发现有些语法想一想是知道&#xff0c;但实际操作起来跟想的情况不一样哈哈。不是遇见bug就是输出的结果不是自己想要的&#xff0c;CSDN跟知乎找了很多没怎么解决&#xff0c;后面多摸索多实操终于解决&#xff01; test_data[item_…

免费提升图片清晰度的AI平台,效果对比一目了然!

随着AI技术的不断发展&#xff0c;我们有了更多的机会去挖掘和提升图片清晰度的可能性。无论是老照片的翻新、档案的修复&#xff0c;还是遥感图像的处理、医学影像的分析&#xff0c;AI都能大显身手。在过去可能很难办到的将分辨率低的图片转为高清图&#xff0c;如今借助AI简…

如何在OpenWRT软路由系统部署uhttpd搭建web服务器实现远程访问——“cpolar内网穿透”

文章目录 前言1. 检查uhttpd安装2. 部署web站点3. 安装cpolar内网穿透4. 配置远程访问地址5. 配置固定远程地址 前言 uhttpd 是 OpenWrt/LuCI 开发者从零开始编写的 Web 服务器&#xff0c;目的是成为优秀稳定的、适合嵌入式设备的轻量级任务的 HTTP 服务器&#xff0c;并且和…

中伟视界:煤矿行业借力人工智能,防控灾害风险迈出新步伐 《“十四五”矿山安全生产规划》(应急(2022)64号),煤矿重大灾害风险防控系统

随着煤矿行业的发展&#xff0c;煤矿重大灾害风险防控成为了行业关注的重点之一。为了更好地预防和应对灾害风险&#xff0c;煤矿行业开始引入人工智能分析算法和检测场景&#xff0c;以提高灾害风险的识别和预警能力。 在煤矿的重大灾害风险防控中&#xff0c;AI算法发挥着重要…

利用C语言模拟实现堆的基本操作和调堆算法

利用C语言模拟实现堆的基本操作和调堆算法 文章目录 利用C语言模拟实现堆的基本操作和调堆算法前言一、堆的基本原理大根堆和小根堆的比较 二、实现堆的基本操作1&#xff09;结构定义2&#xff09;初始化堆&#xff08;HeapInit&#xff09;3&#xff09;销毁堆&#xff08;He…

基于FPGA的视频接口之高速IO

简介 相对于其他视频接口来说,高速IO接口(以Xilinx公司为例,spartan 6系列的GTP、Artix7系列的GTP,KENTEX7系列的GTX和GTH等)具有简化设计、充分利用FPGA资源、降低设计成本等功能。 高速IO接口传输视频,一般会被拓展为万兆以太网、40G以太网、10G光纤、40G光纤、3G-SDI、…

Python:核心知识点整理大全14-笔记

目录 ​编辑 7.2.2 让用户选择何时退出 parrot.py 7.2.3 使用标志 7.2.4 使用 break 退出循环 cities.py 7.2.5 在循环中使用 continue counting.py 7.2.6 避免无限循环 counting.py 7.3 使用 while 循环来处理列表和字典 7.3.1 在列表之间移动元素 confirmed_user…

案例041:基于微信小程序的私家车位共享系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

区别于C端,B端业务私域流量运营新思路解析!

提起私域流量运营&#xff0c;大家都不陌生&#xff0c;什么快餐、美甲、奶茶、蛋糕、披萨&#xff0c;谁都能说两句&#xff0c;但是大家提到的业务&#xff0c;好像都是C端的业务&#xff0c;B端的业务确很少提及。 难道B端不需要私域吗&#xff0c;答案当然是否定的。下面就…

油田中控室与32台碳储罐之间数据无线传输

二氧化碳强化石油开采技术&#xff0c;须先深入了解石油储层的地质特征和二氧化碳的作用机制。现场有8辆二氧化碳罐装车&#xff0c;每辆罐车上有4台液态二氧化碳储罐&#xff0c;每台罐的尾部都装有一台西门子S7-200 smart PLC。在注入二氧化碳的过程中&#xff0c;中控室S7-1…

力扣题:数字与字符串间转换-12.12

力扣题-12.12 [力扣刷题攻略] Re&#xff1a;从零开始的力扣刷题生活 力扣题1&#xff1a;539. 最小时间差 解题思想&#xff1a;将字符串的时间形式换成数字形式的时间&#xff0c;然后计算差值即可&#xff0c;最重要的是最小的值加上一天的时间加入到数组最后&#xff08…

DevOps:自动化、持续交付和持续集成实践

DevOps&#xff1a;自动化、持续交付和持续集成实践 一、DevOps 简介1.1 DevOps 模式定义1.2 DevOps 的工作原理1.3 DevOps 的优势1.4 DevOps 的意义1.5 DevOps 最佳实践 二、持续集成简介2.1 持续集成的意义2.2 持续集成的工作原理2.3 持续集成的优势 三、持续交付简介3.1 持续…

decomposition-based multi-objective algorithm4SPDPTW

关键词 文章概述 研究背景 多目标选择性接送和配送问题&#xff08;PDPs&#xff09;&#xff1a;研究涉及多目标选择性接送和配送问题&#xff0c;这些问题传统上从单一目标角度进行探讨&#xff0c;以寻找最具盈利性的请求集合&#xff0c;同时遵守一系列限制条件。 经济和…

golang https server如何设计方便抓包定位且安全

代码 测试 用go写后端https服务时&#xff0c;需要定位https包中的内容是否符合预期。 有涉猎的朋友应该了解过https有一种keylog技术&#xff0c;它允许在HTTPS连接中捕获和记录SSL或TLS会话密钥&#xff0c;以便于调试和分析加密流量。 本文将的就是通过可控制开启和关闭的…

Android studio 离线配置gradle

Gradle Distributions Gradle Distributions 查看gradle 文件夹下 gradle-wrapper.properties文件中的distributionUrl 版本号 然后在上边网站下载对应需要的gradle对应版本 下载后复制到 gradle wrapper文件下&#xff0c;同时修改 distributionUrl 指向本地文件 然后同步就…

(C++)vector介绍及其使用

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 前言 我们参考cplusplus文档逐个进行解释。 构造函数 push_back&&pop_back vector迭代器的使用 vector空间增长问题 我们发现resize不缩容&#xff0c;当然&#xff0c;这要看编译器的实现&#xff0c;不同的编译…

据房间Id是否存在,判断当前房间是否到期且实时更改颜色

重点代码展示&#xff1a; <template><el-col style"width: 100%;height: 100%;"><el-col :span"20"><el-card class"room_info"><avue-data-icons :option"option"></avue-data-icons></el-…

手动搭建koa+ts项目框架(路由篇)

文章目录 前言一、安装koa-router二、引入koa-router并使用三、优化路由配置总结如有启发&#xff0c;可点赞收藏哟~ 前言 本文基于手动搭建koats项目框架&#xff08;基础篇&#xff09;配置接口路由 一、安装koa-router npm i -S koa-router二、引入koa-router并使用 ./sr…