JDBC基础Demo

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>jdbc</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Add your dependencies here -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
    </dependencies>


    <build>
        <finalName>jdbc</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId><!--构建包含依赖的jar包-->
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.example.JDBCTest01</mainClass><!--指定启动类-->
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

项目结构

 

 增删改

package com.example;

import com.mysql.cj.jdbc.ConnectionImpl;

import java.sql.*;
import java.util.Properties;
import java.util.ResourceBundle;

/**
 * @author hrui
 * @date 2024/8/20 8:27
 */
public class JDBCTest01 {

    public static void main(String[] args){
        //1.注册驱动
//        Driver driver = new com.mysql.cj.jdbc.Driver();
//        DriverManager.registerDriver(driver);
        //Class.forName("com.mysql.cj.jdbc.Driver");//这一步将上面两部做了  新版本这一步也可以省略
        //2.获取连接    在JDBC 4.0之后,可以省略注册驱动的步骤 getConnection时候会读META-INF/services/java.sql.Driver中内容并注册驱动
        Connection connection = null;
        Statement statement = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql:/localhost:3306/jdbc", "root", "123456");
            System.out.println(connection);//com.mysql.cj.jdbc.ConnectionImpl@548ad73b
            //3.获取SQL执行对象
            statement = connection.createStatement();
            //String sql = "insert into user values(null,\"haha\",\"123456\")";
            String sql = "insert into user values(null,\"哈哈\",\"123456\"),(null,\"haha3\",\"123456\")";
            //4.执行sql(executeUpdate专门用于执行DML语句insert delete update 返回影响数据的记录条数)
            int i = statement.executeUpdate(sql);
            System.out.println(i);
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //关闭资源依次从小到大
            if(statement!=null){
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

增删改  以配置文件方式    配置文件放在resources下

package com.example;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Properties;

/**
 * 配置文件方式配置数据库连接
 * @author hrui
 * @date 2024/8/21 12:39
 */
public class JDBCTest02 {
    public static void main(String[] args) {
        Connection connection=null;
        Statement statement=null;
        try {
            //使用类加载器加载 properties 文件
            InputStream input = JDBCTest02.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(input);
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            //获取连接
            connection = DriverManager.getConnection(url, username, password);
            //获取执行对象
            statement = connection.createStatement();
            String sql="insert into user values(null,\"haha3\",\"456\")";
            //执行sql
            int count = statement.executeUpdate(sql);
            System.out.println(count);
        } catch (Exception e) {
            e.printStackTrace();

        }finally {
            if(statement!=null){
                try {
                    statement.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            if(connection!=null){
                try {
                    connection.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
    }
}

resources下创建jdbc.properties 

url=jdbc:mysql://localhost:3306/jdbc
username=root
password=123456

基础查询操作

package com.example;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

/**
 * 查询数据 需要处理结果集
 * @author hrui
 * @date 2024/8/21 14:06
 */
public class JDBCTest03 {
    public static void main(String[] args) {

        Connection connection=null;
        Statement statement=null;
        ResultSet resultSet=null;
        try {
            //使用类加载器加载 properties 文件
            InputStream input = JDBCTest03.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(input);
            String url = prop.getProperty("url");
            String username = prop.getProperty("username");
            String password = prop.getProperty("password");
            connection = DriverManager.getConnection(url, username, password);

            statement = connection.createStatement();
            String sql="select * from user";
            //int executeUpdate (insert/delete/update)
            //ResultSet executeQuery (select)
            resultSet = statement.executeQuery(sql);//专门执行DQL语句的方法

            //注意:所有列都可以转String 类型 但是DECIMAL 或 NUMERIC 可能转换导致丢失精度
            //还有一些特殊类型 可能导致转换不是预期
            while (resultSet.next()){
                //以查询出来的下标获取  注意 下标根据select xxx,xxx,xxx确定
//                int id = resultSet.getInt(1);
//                String name = resultSet.getString(2);
//                String pw = resultSet.getString(3);
                //按查询出来的列明获取 注意是查询结果的列明  如 select id, username as ua, password  那么不应该是username 而是ua
                int id = resultSet.getInt("id");
                String name = resultSet.getString("username");
                String pw = resultSet.getString("password");
                System.out.println(id+":"+name+":"+pw);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (resultSet!=null){
                try {
                    resultSet.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (statement!=null){
                try {
                    statement.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

演示Statement存在sql注入的问题

package com.example;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner;

/**
 * 演示sql注入问题
 * @author hrui
 * @date 2024/8/21 15:33
 */
public class JDBCTest04 {
    public static void main(String[] args) {
        Connection connection=null;
        Statement statement=null;
        ResultSet resultSet=null;

        try {

            Scanner scanner = new Scanner(System.in);
            System.out.println("输入用户名:");
            String username = scanner.nextLine();
            System.out.println("输入密码:");
            String password = scanner.nextLine();
            String sql = "select * from user where username='"+username+"' and password='"+password+"'";
            System.out.println(sql);
            //使用类加载器加载 properties 文件 获取 url username password
            InputStream input = JDBCTest04.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(input);

            connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("username"), prop.getProperty("password"));
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);

            if(resultSet.next()){
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (resultSet!=null){
                try {
                    resultSet.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (statement!=null){
                try {
                    statement.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

SQL注入的原因

  • 直接拼接:由于用户输入的数据直接拼接到 SQL 语句中,并被送入数据库引擎进行编译,恶意的 SQL 代码也参与了编译和执行过程,导致 SQL 注入攻击。
  • 参与编译:用户输入的未经过滤或转义的数据参与了 SQL 语句的编译,导致了 SQL 注入风险。

解决SQL注入问题

Statement  数据库操作对象

PreparedStatement  预编译的数据库操作对象

public interface PreparedStatement extends Statement

解决SQL注入根本在于,用户提供的信息不参与SQL语句的编译过程,这样即使用户提供的信息包含SQL语句的关键字,但是没有参与编译,就会不起作用

PreparedStatement 的原理是:预先对SQL语句进行了编译   

package com.example;

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

/**
 * 解决SQL注入问题
 * @author hrui
 * @date 2024/8/21 15:50
 */
public class JDBCTest05 {
    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;

        try {

            Scanner scanner = new Scanner(System.in);
            System.out.println("输入用户名:");
            String username = scanner.nextLine();
            System.out.println("输入密码:");
            String password = scanner.nextLine();
            String sql = "select * from user where username=? and password=?";

            //使用类加载器加载 properties 文件 获取 url username password
            InputStream input = JDBCTest04.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(input);

            connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("username"), prop.getProperty("password"));
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,username);//是字符串就set字符串  int就setInt
            preparedStatement.setString(2,password);

            resultSet = preparedStatement.executeQuery();//sql不需要在往里传  如果再传的话,会重新编译

            if(resultSet.next()){
                System.out.println("登录成功");
            }else {
                System.out.println("登录失败");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (resultSet!=null){
                try {
                    resultSet.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (preparedStatement!=null){
                try {
                    preparedStatement.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

对比Statement和PreparedStatement

1.Statement存在SQL注入风险

2.PreparedStatement预编译,Statement是编译一次执行一次,PreparedStatement编译一次 可执行多次,效率相对高.PreparedStatement会做类型安全检查(就是你setString 结果出入的是100 编译器报错)

package com.example;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Properties;

/**
 * PrepareStatement 增删改
 * @author hrui
 * @date 2024/8/21 16:28
 */
public class JDBCTest06 {
    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {

            InputStream resourceAsStream = JDBCTest06.class.getClassLoader().getResourceAsStream("jdbc.properties");
            Properties prop = new Properties();
            prop.load(resourceAsStream);

            connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("username"), prop.getProperty("password"));
            preparedStatement = connection.prepareStatement("insert into user(username,password) values(?,?)");
            preparedStatement.setString(1,"hrui");
            preparedStatement.setString(2,"123456");
            int i = preparedStatement.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (preparedStatement!=null){
                try {
                    preparedStatement.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

JDBC事务机制  默认是自动提交

JDBC工具类封装

package com.example;

import java.sql.*;
import java.util.ResourceBundle;

/**
 * @author hrui
 * @date 2024/8/21 16:51
 */
public class DBUtil {
    //静态变量:在类加载时候执行,并且是有先后顺序的.自上而下
    private static ResourceBundle bundle=ResourceBundle.getBundle("resource1.jdbc");
    //JDBC4开始  DriverManager.getConnection会读Mysql驱动包中的配置文件
    //配置文件在META-INF/META-INF/services/java.sql.Driver
    //private static String driver=bundle.getString("driver");
    private static String url=bundle.getString("url");
    private static String username=bundle.getString("username");
    private static String password=bundle.getString("password");

//    static{
//        //注册驱动(注册却动只需要注册一次,放在静态代码块当中.DBUtil类加载的时候执行)
//        try {
//            //"com.mysql.jdbc.Driver"是连接数据库的驱动,不能写死,因为可能以后改成Oracle数据库
//            //如果连接Oracle数据库的时候,还需要修改java代码,显然违背OCP开闭原则
//            //OCP开闭原则:对扩展开发,对修改关闭.(什么是复合OCP呢?在进行功能扩展的时候,不需要修改java源代码)
//            //Class.forName("com.mysql.cj.jdbc.Driver");
//            //Class.forName(driver);
//            DriverManager.getConnection(url,username, password);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }

    //获取数据库连接对象  抛异常,谁使用,谁负责
    public static Connection getConnection() throws SQLException {
        //JDBC4开始  DriverManager.getConnection会读Mysql驱动包中的配置文件
        //配置文件在META-INF/META-INF/services/java.sql.Driver
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }

    //关闭连接 释放资源

    /**
     * 释放资源
     * @param conn 数据库连接对象
     * @param st 执行对象
     * @param rs 结果集对象
     */
    public static void close(Connection conn, Statement st, ResultSet rs){

        if (conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

注意模糊查询时候的错误写法

行级锁   也被称为悲观锁   悲观锁概念:数据锁住了

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

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

相关文章

STL六大组件

STL&#xff08;Standard Template Library&#xff0c;标准模板库&#xff09;是C标准库的一部分&#xff0c;提供了丰富且高效的数据结构和算法。STL主要由6大组件构成&#xff0c;分别是容器、算法、迭代器、适配器、仿函数和空间配置器。 容器&#xff08;Containers&#…

ES6 (一)——ES6 简介及环境搭建

目录 简介 环境搭建 可以在 Node.js 环境中运行 ES6 webpack 入口 (entry) loader 插件 (plugins) 利用 webpack 搭建应用 gulp 如何使用&#xff1f; 简介 ES6&#xff0c; 全称 ECMAScript 6.0 &#xff0c;是 JavaScript 的下一个版本标准&#xff0c;2015.06 发版…

ICC2:insertion delay会拉长同一skew group其他sink吗?

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 来自知识星球提问: 已知一个skew group包含若干sink,针对其中一个sink设置insertion delay,希望工具把它做长,命令如下: create_clock_skew_group -clock xx -objects {xx xx} -name sg set_cl…

2024 江苏省第二届数据安全技术应用职业技能竞赛 初赛 部分wp

文章目录 一、前言二、参考文章三、题目&#xff08;解析&#xff09;数据安全解题赛1、ds_0602&#xff08;30分&#xff09;2、333.file&#xff08;45分&#xff09;3、pf文件分析&#xff08;35分&#xff09;4、丢失的资料&#xff08;45分&#xff09;5、greatphp&#x…

C#学习之路day2

一、变量 用来在存储计算机当中存储数据 1、常见的数据类型&#xff0c; 2、声明变量的方式 *声明&#xff1a;变量类型 变量名 &#xff1b; *赋值&#xff1a;变量名 值 &#xff1b; 先声明 &#xff0c;再赋值 &#xff0c;再使用 int num ; //声明num 10; //赋值i…

ArcGIS Pro 实现人口分布栅格TIFF数据的网格提取与可视化

这里在分享一个人口1km精度栅格数据&#xff0c;LandScan是由美国能源部橡树岭国家实验室&#xff08;ORNL&#xff09;提供的全球人口分布数据集&#xff0c;具有最高分辨率的全球人口分布数据&#xff0c;是全球人口数据发布的社会标准&#xff0c;是全球最为准确、可靠&…

React原理之Fiber双缓冲

前置文章&#xff1a; React原理之 React 整体架构解读React原理之整体渲染流程React原理之Fiber详解 -----读懂这一篇需要对 React 整体架构和渲染流程有大致的概念 &#x1f60a;----- 在前面的文章中&#xff0c;简单介绍了 Fiber 架构&#xff0c;也了解了 Fiber 节点的…

macOS安装搭建python环境

安装Homebrew apt-get是一个常见于Debian和Ubuntu等基于Linux的操作系统中的包管理工具&#xff0c;用于安装、更新和移除软件包。然而&#xff0c;macOS使用的是Homebrew或者MacPorts等其他的包管理工具&#xff0c;并不使用apt-get。 如果你想在macOS上使用类似apt-get的功…

书生大模型实战营-进阶关-Lagent 自定义你的 Agent 智能体

Lagent 自定义你的 Agent 智能体 Lagent 介绍环境配置Lagent Web体验第1步&#xff0c;启动大模型API服务第2步&#xff0c;启动 Lagent 的 Web页面 基于 Lagent 自定义智能体 Lagent 介绍 Lagent 是一个轻量级、开源的基于大语言模型的智能体&#xff08;agent&#xff09;框…

家里猫毛到处飞怎么办?如何清理?用宠物空气净化器去除猫毛

我家三只布偶原住民&#xff0c;都是掉毛怪&#xff0c;刚好还是不同的颜色&#xff0c;黑的灰的白的...家里和画板似的&#xff0c;每天都被猫毛上色&#xff0c;清扫时超级崩溃。沙发上、床上、地板上这些常见的地方就不用说了&#xff0c;甚至水杯和碗筷边偶尔也能看见猫毛&…

微服务的基本理解和使用

目录​​​​​​​ 一、微服务基础知识 1、系统架构的演变 &#xff08;1&#xff09;单体应用架构 &#xff08;2&#xff09;垂直应用架构 &#xff08;3&#xff09;分布式SOA架构 &#xff08;4&#xff09;微服务架构 &#xff08;5&#xff09;SOA与微服务的关系…

wincc报警如何通过短信发送给手机

单位使用WINCC上位机监控现场&#xff0c;需要把报警信息发送到指定手机上&#xff0c;能否实现&#xff1f;通过巨控GRMOPC系列远程智能控制终端&#xff0c;简单配置即可实现wincc报警短信传送到手机。配置过程无需任何通讯程序&#xff0c;也不要写任何触发脚本。 GRMOPC模…

Java中接口

接口的定义和使用 练习 public abstract class Animal {private String name;private int age;public Animal() {}public Animal(String name, int age) {this.name name;this.age age;}public String getName() {return name;}public void setName(String name) {this.name…

LIN通讯

目录 1 PLinApi.h 2 TLINFrameEntry 结构体 3 自定义函数getTLINFrameEntry 4 TLINScheduleSlot 结构体 5 自定义函数 getTLINScheduleSlot 6 自定义LIN_SetScheduleInit函数 7 自定义 LIN_StartSchedule 8 发送函数 9 线程接收函数 1 PLinApi.h 这是官方头文件 ///…

开源原型设计工具Penpot

Penpot是一个现代化、开源的协同设计平台&#xff0c;专为跨职能团队打造&#xff0c;提供了强大的在线设计和原型制作功能。 以下是对Penpot的详细介绍&#xff1a; 一、平台特点 开源与免费&#xff1a;Penpot是一个完全免费且开放源代码的项目&#xff0c;允许社区贡献和定…

20:【stm32】定时器一:时基单元

时基单元 1、什么是定时器2、时基单元的基本结构2.1&#xff1a;脉冲的来源2.2&#xff1a;预分频器PSC2.3&#xff1a;计数器CNT2.4&#xff1a;update事件与预加载 3、标准库编程3.1&#xff1a;通过定时器中断来设置延迟函数 1、什么是定时器 定时器是一种专门负责定时功能…

45.【C语言】指针(重难点)(H)

目录&#xff1a; 22.函数指针变量 *创建 *使用 *两段代码分析 23.函数指针数组 *基本用法 *作用 往期推荐 22.函数指针变量 *创建 类比数组指针变量的定义&#xff1a;存放数组地址的指针变量&#xff0c;同理函数指针变量存放函数的地址 格式 函数的返回类型 (*指针变量的…

产品帮助中心如何搭建?五步让客户满意度提升100%

一、引言 创建帮助文章的好处是节省了招募大量客户联系代理的昂贵成本。它们现在通过解决客户的早期问题而无需支持干预&#xff0c;并为自助提供逐步指导&#xff0c;从而取代了支持代理。 当您创建帮助文章时&#xff0c;您会构建知识库并为将来保留它。这些帮助文章充当新…

作业帮 TiDB 7.5.x 使用经验

作者&#xff1a; 是我的海 原文来源&#xff1a; https://tidb.net/blog/5f9784d3 近期在使用 TiDB 时遇到的一些小问题的梳理总结&#xff0c;大部分版本都在6.5.6和7.5.2 1、limit 导致的扫描量过大的优化 研发定时任务每天需要扫描大量数据&#xff0c;到时机器网卡被…

开放式耳机好还是入耳式耳机好?2024五款热销开放式耳机推荐!

开放式耳机与入耳式耳机各有优缺点&#xff0c;适合不同的使用场景和用户需求。 开放式耳机的优点主要包括&#xff1a; 1. 佩戴舒适性好&#xff0c;由于设计宽松&#xff0c;不会给耳朵带来压迫感&#xff0c;适合长时间使用 。 2. 透气性能好&#xff0c;尤其在夏天或运动…