MySQL数据库-JDBC篇

认识JDBC

先了解什么是数据库连接驱动

数据库驱动:是连接应用程序和数据库的关键,我们的程序会通过数据库驱动,来和数据库打交道!!!

SUN公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,俗称JDBC
那么这些规范的实现由具体的厂商去做
对于开发人员来说,我们只需要掌握JDBC接口的操作即可!

下载和导入数据库驱动

一、下载
1、下载地址:https://dev.mysql.com/downloads/

2、点击Connerctor/J,选择框起来的选项,表示与平台无关

3、下载这个压缩文件

4、弹出来的界面选择如下:

5、将解压后的文件放在指定的位置

二、导入IDRA
1、在新建的项目下建一个lib目录

2、将我们下载好的jar包复制进来

3、右键lib目录,点击 Add as Library

4、点击OK

5、发现这个jar包是可以展开的,说明我们已经成功将jar包导入到项目中

第一个JDBC程序(标准的操作步骤)

一、操作步骤
1、pom.xml中导入连接是数据库的jar包,类中加载JDBC驱动;
2、编写用户的账号和密码以及URL路径;
3、驱动连接数据库,返回连接的对象connection;
4、连接对象connection创建执行SQL的对象statement;
5、执行SQL对象调用查询或者更新的方法(executeQuery)执行SQL语句,并且返回一个结果集;
6、释放连接

二、测试代码(其中第一步和第二步的代码是固定的,背过!!!)
数据库表:

IDEA代码:
导入依赖:

<!--        导入数据库连接驱动的jar包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
    </dependencies>

具体代码如下:

import java.sql.*;

// 我的第一个JDBC程序
public class jdbcFirst {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1、加载驱动,记住这个加载方式,这是固定的写法
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2、用户信息和URL,记住这个路径,也是固定写法!!!!!!!!!!
        /*useUnicode=true 表示支持中文编码
         * characterEncoding=utf8 表示设置字符集编码
         * useSSL=true 表示使用安全的连接
         * "?" 的作用是连接参数
         * "&"表示and 和
         * URL 表示唯一定位:
         * MySQL公式:协议://主机地址:端口号(默认3306)/数据库名?参数1&参数2&参数3;
         * oralce公式: jdbc:oralce:thin@localhost:1521(默认1521):sid
         * */
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
        String username = "root";
        String password = "root";

        //3、连接数据库,返回数据库对象 Connection代表数据库,同样还可以在这个级别上设置自动提交事务,回滚等操作
        Connection connection = DriverManager.getConnection(url, username, password);
        /*//数据库级别的操作常见如下:
        connection.commit(); //提交事务
        connection.setAutoCommit(true);// 设置是否自动提交
        connection.rollback(); //回滚事务*/

        //4、执行SQL对象  statement是用来执行SQL的对象
        Statement statement = connection.createStatement();

        //5、执行SQL的对象  去执行SQL,可能存在结果,查看返回的结果
        String sql1 = "SELECT * FROM users"; //定义查询语句
        //注意:statement调用的只有Query 和 update 方法,因为insert 和 delete 都归在了update下,executeUpdate()返回受影响的行数
        //statement.execute();//增删改查的语句都可以执行
        ResultSet resultSet = statement.executeQuery(sql1);// resultSet只有查询的时候会有,返回一个结果集,链表的形式,结果集中封装了全部的查询的结果
        while (resultSet.next()) { //resultSet.next()返回值是一个布尔类型,如果结果集中后面没有数据就返回false
            System.out.println("id = " + resultSet.getObject("id"));// getObject是在不知道列数据类型的时候使用,resultSet还可以调用特定类型的方法
            System.out.println("name = " + resultSet.getObject("NAME"));
            System.out.println("pwd = " + resultSet.getObject("PASSWORD"));
            System.out.println("email = " + resultSet.getObject("email"));
            System.out.println("birthday = " + resultSet.getObject("birthday"));
            System.out.println("=============================================");
        }
        //6、释放连接,必须要做(连接很占内存,必须释放资源)
        resultSet.close();
        statement.close();
        connection.close();

    }

}

抽取JDBC为一个工具类

1、新建一个包,名字叫做utils

2、工具类中将加载驱动的方法写到static静态代码块中,随着类的加载而加载,这样只需要将加载驱动的方法执行一次即可
然后将连接数据库和释放资源的功能写成一个方法,将来直接调用即可

import com.mysql.cj.protocol.Resultset;

import javax.xml.stream.events.StartDocument;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    //将我们用到的变量提升一下作用域
    private static String driver;
    private static String url;
    private static String username;
    private static String password;

    static {
        try {
            // 1、通过工具类,获取他自己的反射对象,然后获取反射对象的类加载器,调用类加载器的获取资源的方法
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //2、创建读取配置文件的对象
            Properties properties = new Properties();
            //3、调用读取配置文件的方法
            properties.load(in);
            //4、获取配置文件中的value
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //加载JDBC的Driver驱动,因为是放在了静态代码块中,所以只需要加载一次即可
            Class.forName(driver);
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //连接数据库方法
    public static Connection getConnection() throws SQLException {
        //连接数据库
        return DriverManager.getConnection(url, username, password);
    }

    //释放资源方法
    public static void release(Connection conn, Statement sta, ResultSet rs) throws SQLException {
        if (rs != null) {
            rs.close();
        }
        if (sta != null) {
            sta.close();
        }
        if (conn != null) {
            conn.close();
        }
    }
}

运用工具类完成增删改查

在IDEA中,增删改都直接调用Update方法,查询调用excuteQuery方法
测试表:

一、增删改

public class testInsert {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement sta = null;
        ResultSet rs = null;

        try {
            //获取连接,因为我们将JDBC封装成一个工具类,这里直接调用工具类的方法即可
            conn = JdbcUtils.getConnection();
            //获取执行sql的对象
            sta = conn.createStatement();
            //编写需要的SQL语句
            String sql = "INSERT INTO users (id,`NAME`,`PASSWORD`,`email`,birthday)" +
                    "VALUES (4,'张三','1232456445','12345@qq.com','2023-01-23');";
            //凡是增、删和改都用Update这个方法,返回一个int类型受影响的行数
            int i = sta.executeUpdate(sql);
            if (i != 0){
                System.out.println(i + "条数据插入成功!");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //当操作结束后,调用释放资源的方法
            JdbcUtils.release(conn,sta,rs);
        }
    }
}

二、查询

public class testQuery {
    public static void main(String[] args) {
        Connection conn = null;
        Statement sta = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            sta = conn.createStatement();
            String sql = "SELECT *  FROM users";
            rs = sta.executeQuery(sql);
            while (rs.next()){
                System.out.println("id:" + rs.getInt("id"));
                System.out.println("NAME:" + rs.getString("NAME"));
                System.out.println("PASSWORD:" + rs.getInt("PASSWORD"));
                System.out.println("email:" + rs.getObject("email"));
                System.out.println("birthday:" + rs.getObject("birthday"));
                System.out.println("============================");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            try {
                JdbcUtils.release(conn,sta,rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

}

SQL注入

SQL语句可以实现拼接(也就存在漏洞),如果我们 写的业务中没有屏蔽这种SQL注入问题,程序就会被攻击

下面演示一段SQL注入代码:

public class testLogin {
    public static void main(String[] args) {
        //主方法中调用登陆的业务,写一个"'or '1 = 1", "'or '1 = 1"的username h和password 这样就会让where条件判断一直保持true
        login("'or '1 = 1", "'or '1 = 1");
    }

    //登陆业务
    public static void login(String username, String password) {
        Connection conn = null;
        Statement sta = null;
        ResultSet rs = null;

        try {
            //获取连接,因为我们将JDBC封装成一个工具类,这里直接调用工具类的方法即可
            conn = JdbcUtils.getConnection();
            //获取执行sql的对象
            sta = conn.createStatement();
            //编写需要的SQL语句
            String sql = "select * from users where `NAME` = '" + username + "'AND PASSWORD = '" + password + "'";
            //凡是增、删和改都用Update这个方法,返回一个int类型受影响的行数
            rs = sta.executeQuery(sql);
            while (rs.next()) {
                System.out.println("id:" + rs.getInt("id"));
                System.out.println("NAME:" + rs.getString("NAME"));
                System.out.println("PASSWORD:" + rs.getInt("PASSWORD"));
                System.out.println("email:" + rs.getObject("email"));
                System.out.println("birthday:" + rs.getObject("birthday"));
                System.out.println("============================");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //当操作结束后,调用释放资源的方法
            try {
                JdbcUtils.release(conn, sta, rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

输出的结果:
写一段拼接的SQL就会将所有的信息全部查询出来

PreparedStatement对象

这个对象可以防止SQL注入,并且效率会更高

一、PreparedStatement对象增删改的代码

public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement sta = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();

            //value中的问号表示占位符,用prepareStatement方法的优势就是可以最后添加value
            String sql = "INSERT INTO users (id,`NAME`,`PASSWORD`,`email`,birthday) VALUES(?,?,?,?,?)";

            //区别于 statement
            /*1、prepareStatement对象可以直接被数据库conn对象创建,而statement对象还需要conn对象调用createStatement()方法才能创建
             * 2、prepareStatement()方法需要传入一个参数,这个参数是预编译的SQL语句,通俗讲是先写SQL,暂时不执行
             * 3、提前将写好的SQL放进方法中
             * */
            sta = conn.prepareStatement(sql);
            sta.setInt(1, 4);
            sta.setString(2, "10086");
            sta.setString(3, "123456789");
            sta.setString(4, "244562@qq.com");
            //注意:这里的date是先调用SQL的date
            //然后调用的是java中的 until下的date,getTime是获取当前时间戳
            sta.setDate(5, new java.sql.Date(new Date().getTime()));
            //真正的执行方法,区别于statement调用这个方法还需要往里面传入sql,而prepareStatement不需要往里面传SQL语句了
            int i = sta.executeUpdate();
            if (i > 0 ){
                System.out.println(i + "行被插入!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            try {
                JdbcUtils.release(conn, sta, rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

二、查询代码

public class TestQuery {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement sta = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();

            //value中的问号表示占位符,用prepareStatement方法的优势就是可以最后添加value
            String sql = "select * from users where id = ?";

            //区别于 statement
            /*1、prepareStatement对象可以直接被数据库conn对象创建,而statement对象还需要conn对象调用createStatement()方法才能创建
             * 2、prepareStatement()方法需要传入一个参数,这个参数是预编译的SQL语句,通俗讲是先写SQL,暂时不执行
             * 3、提前将写好的SQL放进方法中
             * */
            sta = conn.prepareStatement(sql);
            sta.setInt(1,3);
            //真正的执行方法,区别于statement调用这个方法还需要往里面传入sql,而prepareStatement不需要往里面传SQL语句了
            rs = sta.executeQuery();
            if (rs.next()){
                System.out.println(rs.getString("NAME"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            try {
                JdbcUtils.release(conn, sta, rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}


三、防止SQL注入的原因

见下面的代码以及注释

public class testLogin {
    public static void main(String[] args) {
        //主方法中调用登陆的业务
        //1、正常的参数
        login("10086","123456789");
        //2、SQL注入的参数
        login("'or '1 = 1", "'or '1 = 1");
    }

    //登陆业务
    public static void login(String username, String password) {
        Connection conn = null;
        PreparedStatement sta = null;
        ResultSet rs = null;

        try {
            //获取连接,因为我们将JDBC封装成一个工具类,这里直接调用工具类的方法即可
            conn = JdbcUtils.getConnection();

            //编写需要的SQL语句
            String sql = "select * from users where `NAME` = ? and  `PASSWORD` = ?";
            //获取执行sql的对象,进行预编译
            //prepareStatement防止SQL注入的本质在于,他将传进来的参数都当作字符,假设其中存在‘’这种转义字符,会被直接转义
            sta = conn.prepareStatement(sql);
            //给value赋值
            sta.setString(1,username);
            sta.setString(2,password);
            rs = sta.executeQuery();
            while (rs.next()) {
                System.out.println("id:" + rs.getInt("id"));
                System.out.println("NAME:" + rs.getString("NAME"));
                System.out.println("PASSWORD:" + rs.getInt("PASSWORD"));
                System.out.println("email:" + rs.getObject("email"));
                System.out.println("birthday:" + rs.getObject("birthday"));
                System.out.println("============================");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //当操作结束后,调用释放资源的方法
            try {
                JdbcUtils.release(conn, sta, rs);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}

Statement对象

使用statement 对象存在SQL注入的问题,不安全,一般多用PreparedStatement对象!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
您好!感谢您的提问。对于MySQL JDBC连接,您可以按照以下步骤进行操作: 1. 首先,确保您已经安装了Java Development Kit (JDK) 和 MySQL数据库。 2. 在您的Java项目中,添加MySQL JDBC驱动程序。您可以在MySQL官方网站上下载适用于您的操作系统和MySQL版本的JDBC驱动程序,并将其添加到项目的classpath中。 3. 在Java代码中,使用`java.sql`包中的相关类来建立数据库连接。以下是一个简单的示例代码: ```java import java.sql.*; public class Main { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydatabase"; // 数据库URL String username = "your-username"; // 数据库用户名 String password = "your-password"; // 数据库密码 try { // 加载驱动程序 Class.forName("com.mysql.cj.jdbc.Driver"); // 建立数据库连接 Connection connection = DriverManager.getConnection(url, username, password); // 执行SQL查询或更新操作 // ... // 关闭数据库连接 connection.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } } ``` 在上面的示例代码中,`url`变量指定了数据库的URL,其中包括主机名、端口号和数据库名称。`username`和`password`变量存储了登录数据库所需的用户名和密码。 4. 在建立连接后,您可以使用`Connection`对象执行SQL查询或更新操作。具体的操作取决于您的需求和业务逻辑。 5. 最后,别忘记在完成数据库操作后关闭连接,使用`connection.close()`方法。 请注意,以上示例代码仅为演示目的,并未进行错误处理和异常处理。在实际开发中,您应该根据需要添加适当的错误处理和异常处理机制。 希望这能帮助到您!如果您有任何其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Be explorer

若认可笔者文章,手头富裕望支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值