JAVA-Web后端学习3 JDBC

不思議だね いまの気持ち,空から降ってきたみたい

JDBC

JDBC(JAVA Database Connectivity),使用java操作关系型数据库的一套API

JDBC测试

接下来一个简单的单元测试程序,使用JDBC连接DQL(数据查询语句),来跑一遍JDBC流程

创建一个Maven项目,首先需要在Maven的POM.XML中添加JDBC以及其他相关依赖
注意,这里配置的时候一定要结合本地的JDK来配置版本号,否则编译会出错

<dependencies>
    <dependency>
        <!-- JDBC连接依赖 -->
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.0.33</version>
    </dependency>
    <dependency>
        <!-- 单元测试依赖 -->
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.9.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <!-- lombok依赖 -->
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.42</version>
    </dependency>
</dependencies>

然后在test包下创建测试程序

//JdbcTest.java
public class JdbcTest {
    @Test
    public void testQuery() throws ClassNotFoundException, SQLException {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取数据库连接
        String url = "jdbc:mysql://localhost:3306/dbtest";
        String username = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url,username,password);

        //3.获取SQL语句执行对象
        Statement statement = connection.createStatement();

        //4.执行SQL
        statement.executeQuery("select * from user");

        //5.释放资源
        statement.close();
        connection.close();
    }
}

JDBC查询结果

首先 根据数据库元素设置一个封装数据库数据的实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserData {
    private Integer id; //ID
    private String username; //用户名
    private String password; //密码
    private String name; //姓名
    private Integer age; //年龄
}

然后简单修改一下代码
这里出现了两个新概念
ResultSet结果集对象 statement.executeQuery()的返回类型
next()方法 将光标从当前位置向前移动一行并判断当前行是否为有效行,返回为boolean类型,如果为true则是有效行有数据,为false则是无效行没有数据

public class JdbcTest {
    @Test
    public void testQuery() throws ClassNotFoundException, SQLException {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.获取数据库连接
        String url = "jdbc:mysql://localhost:3306/dbtest";
        String username = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url,username,password);
        //3.获取SQL语句执行对象
        Statement statement = connection.createStatement();
        //4.执行SQL
        ResultSet rs = statement.executeQuery("select * from user"); //这里使用了ResultSet结果集
        //5.处理结果集
        while(rs.next()) {//next()方法
            UserData userData = new UserData(
                    rs.getInt("id"),
                    rs.getString("username"),
                    rs.getString("password"),
                    rs.getString("name"),
                    rs.getInt("age")
            );
            System.out.println(userData);
        }

        //6.释放资源
        statement.close();
        connection.close();
    }
}

执行效果如下:
image

预编译SQL

如果我要使用JDBC查询username为lvbu,且age为28的该如何查询,有两种方式

//方法一
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("select * from user where username='lvbu' and age=28");

//方法二
PreparedStatement pstmt = connection.prepareStatement("select * from user where username = ? and age = ?");
pstmt.setString(1,"lvbu");
pstmt.setInt(2,28);
ResultSet rs = pstmt.executeQuery();

可以看到,方法一穿进去的sql写死了参数,方法二则是使用符号?动态传递了参数,也就是预编译SQL

预编译SQL有两大优势:①防止SQL注入,安全性更好 ②性能更高

SQL注入

SQL注入是一种网络安全漏洞,攻击者通过在应用程序的输入字段中插入恶意的SQL代码,从而能够操纵后端数据库查询。这种攻击方式利用了应用程序在处理用户输入时缺乏适当的验证和过滤机制。
采用上述方法一时,当应用程序直接将用户输入拼接到SQL查询语句中时,攻击者可以构造特殊的输入来改变查询的逻辑。例如,如果一个登录表单的查询语句是:

SELECT * FROM users WHERE username = '输入值' AND password = '输入值'

攻击者可以将用户名输入为 ' OR '1'='1,这样最终的查询语句就变成了:

SELECT * FROM users WHERE username = '' OR '1'='1' AND password = '输入值'

由于 '1'='1' 永远为真,攻击者就可能绕过身份验证,获得对数据库的未授权访问。

SQL注入攻击可能导致数据泄露、数据篡改、数据删除等严重后果,因此在开发应用程序时必须采取适当的防护措施,如使用参数化查询、输入验证和过滤等技术。

提升性能

就像计算机语言会经过一系列步骤从而翻译成机器指令一样,SQL语句输入进来后也需要经过一系列步骤(解析SQL语句,优化SQL语句,编译SQL语句,执行SQL语句)才可以执行。


现在的SQL系统为了优化SQL执行步骤提升性能,例如openGauss的PBE(Parse,Bind,Execute),对于SQL语句解析(Parse)之后生成SQL执行计划(Plan)并将执行计划和SQL语句绑定(Bind),然后执行(Execute),而如果同一SQL语句大量重复执行的话那么可直接在内存里缓存其执行计划,然后每一次SQL语句传来时直接进行绑定和执行,也就是PBEBEBEBE...


那么相较于简单查询语句,预编译语句由于参数设置为动态绑定,因此减少了解析和编译次数,同时在PBE方面也是极大了减少了内存负担,从而提升性能。

posted @ 2026-03-19 17:12  tcswuzb  阅读(1)  评论(0)    收藏  举报