当前位置:首页 » 《随便一记》 » 正文

Java连接mysql数据库

29 人参与  2023年05月06日 18:49  分类 : 《随便一记》  评论

点击全文阅读


文章目录

一、Java连接mysql数据库1.1 流程1.2 一个测试连接的java程序 二、优化:创建一个工具类2.1 存在的问题2.2 创建配置文件和工具类2.3 测试使用工具类进行CRUD操作 三、SQL注入问题3.1 SQL注入示例 四、使用PreparedStatement防止SQL注入五、JDBC操作事务

一、Java连接mysql数据库

1.1 流程

java连接mysql大致需要这六步:

导入驱动包:这里我使用的是mysql-connector-java-8.0.17.jar(点击下载),这个包连接mysql5.6,5.7,8.0版本都没问题。
Class.forName("com.mysql.cj.jdbc.Driver");url和账户名密码
JDBC连接串:jdbc:mysql://<地址>:<端口>/<数据库>获取连接DriverManager.getConnection(url, user, password);执行sql的Statement对象connection.createStatement();执行SQL释放连接

1.2 一个测试连接的java程序

JdbcFirstDemo.java

package com.peng.less01;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class JdbcFirstDemo {    public static void main(String[] args) throws ClassNotFoundException, SQLException {        // 1.导入驱动类        Class.forName("com.mysql.cj.jdbc.Driver");        // 2.用户信息和url        String url = "jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false";        String user = "root";        String password = "12345678";        // 3.获取连接        Connection conn = DriverManager.getConnection(url, user, password);        // 4.执行SQL的对象        Statement sta =  conn.createStatement();        // 5.执行SQL        String sql = "select * from account";        ResultSet rs = sta.executeQuery(sql);        while (rs.next()){            System.out.println("id= " + rs.getObject("id"));            System.out.println("name= " + rs.getObject("name"));            System.out.println("money= " + rs.getObject("money"));            System.out.println("=========================================");        }        // 6.释放连接        rs.close();        sta.close();        conn.close();    }}

这里使用的是VScode,connector包放到了lib目录下,代码放在了src/com/peng/less01下。
执行结果如下,显示了shop.account表下面的三条记录。
在这里插入图片描述

二、优化:创建一个工具类

2.1 存在的问题

1、JDBC连接串,用户名,密码等都存在于代码中,需要进行解耦

2、创建连接,释放连接这些操作都是固定的,没必要每次都重复写这些代码(创建函数解决

2.2 创建配置文件和工具类

src/db.properties 文件中记录driver,url,user,password

driver=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=falseuser=rootpassword=12345678

src/com/peng/less02/utils/JdbcUtils.java 工具类:读取properties配置文件
自动读取配置信息,加载mysql驱动。

package com.peng.less02.utils;import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.Properties;// 这是一个工具类,用来减少重复操作public class JdbcUtils {    private static String driver = null;    private static String url = null;    private static String user = null;    private static String password = null;    static{                try{            // 读取db.properties            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");            Properties properties = new Properties();            properties.load(in);            driver = properties.getProperty("driver");            url = properties.getProperty("url");            user = properties.getProperty("user");            password = properties.getProperty("password");            // 加载驱动            Class.forName(driver);          }catch (Exception e){            e.printStackTrace();        }    }    // 创建连接    public static Connection getConnection() throws SQLException{        return DriverManager.getConnection(url,user,password);    }    // 释放连接    public static void releaseConnection(Connection conn, Statement sta, ResultSet rs){        if (rs != null){            try {                rs.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        if (sta != null){            try {                sta.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        if (conn != null){            try {                conn.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }}

2.3 测试使用工具类进行CRUD操作

测试插入操作
src/com/peng/less02/TestInsert.java

package com.peng.less02;import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import com.peng.less02.utils.JdbcUtils;public class TestInsert {    public static void main(String[] args) {        Connection conn = null;        Statement sta = null;        ResultSet rs = null;        try {            conn = JdbcUtils.getConnection();            sta = conn.createStatement();            String sql = "insert into account(`id`,`name`,`money`) values(4,'药水哥',4698888)";            int i = sta.executeUpdate(sql);            if (i > 0){                System.out.println("插入成功!");            }        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(conn, sta, rs);        }    }    }

测试更新操作
src/com/peng/less02/TestUpdate.java

package com.peng.less02;import java.sql.*;import com.peng.less02.utils.JdbcUtils;public class TestUpdate {    public static void main(String[] args) {        Connection conn = null;        Statement sta = null;        try {            conn = JdbcUtils.getConnection();            sta = conn.createStatement();            String sql = "update account set `money`=238888 where id=3";            int i = sta.executeUpdate(sql);            if (i > 0){                System.out.println("更新成功");            }        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(conn, sta, null);        }    }    }

测试读取操作

package com.peng.less02;import java.sql.*;import com.peng.less02.utils.JdbcUtils;public class TestSelect {    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 account";            rs = sta.executeQuery(sql);            while (rs.next()){                System.out.println("id= " + rs.getInt("id"));                System.out.println("name= " + rs.getString("name"));                System.out.println("money= " + rs.getObject("money"));                System.out.println("======================================================");            }        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(conn, sta, rs);        }    }}

三、SQL注入问题

这里写一个登录认证程序,如果账号,密码输入正确则允许登录。为了测试,这里的允许登录改为输出账号密码。

还使用前面写的JdbcUtils工具类

可以看到,这里我输入的用户名/密码是:’ or '1=1     ’ or '1=1
然后输出了user表中的所有数据,这明显是不合法的。存在sql注入的问题

问题就在于这段代码,sql是拼接而成的。

String sql = "select * from user where `username`='" + username + "' and `password`='" + password + "'";

拼接的sql为:select * from user where `username`='' or '1=1' and `password`='' or '1=1';

3.1 SQL注入示例

SqlInjection.java

package com.peng.less02;import com.peng.less02.utils.JdbcUtils;import java.sql.*;public class SqlInjection {    public static void main(String[] args) {        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 {            conn = JdbcUtils.getConnection();            sta = conn.createStatement();            //这段代码中sql是变量拼接而成的            String sql = "select * from user where `username`='" + username + "' and `password`='" + password + "'";            rs = sta.executeQuery(sql);            //输入正确的账号密码就能够登录,这里为了测试就(输入正确输出账号密码)            while (rs.next()){                System.out.println("id= " + rs.getInt("id"));                System.out.println("username= " + rs.getString("username"));                System.out.println("password= " + rs.getObject("password"));                System.out.println("======================================================");            }        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(conn, sta, rs);        }    }}

在这里插入图片描述

四、使用PreparedStatement防止SQL注入

使用PreparedStatement,防止SQL注入,同时对于执行多次的SQL更加高效

PreparedStatement对sql进行了预编译,传入的参数只会被当作字符串来处理,而不会像前面对sql进行了拼接。

流程如下:

先编写sql --> 进行预编译 --> 增加sql参数值 --> 执行sql

SqlInjection.java

package com.peng.less03;import com.peng.less02.utils.JdbcUtils;import java.sql.*;public class SqlInjection {    public static void main(String[] args) {        // login("'' or 1=1", "'' or 1=1");        login("张三", "zhangsan");    }    // 登录功能    public static void login(String username, String password){        Connection conn = null;        PreparedStatement psta = null;        ResultSet rs = null;        try {            conn = JdbcUtils.getConnection();            //这里使用 ? 占位符来代替            String sql = "select * from user where `username`=? and `password`=?";            //使用PreparedStatement,防止SQL注入,同时对于执行多次的SQL更加高效            psta = conn.prepareStatement(sql);            psta.setString(1,username);            psta.setObject(2,password);            rs = psta.executeQuery();            //输入正确的账号密码就能够登录,这里为了测试就(输入正确输出账号密码)            while (rs.next()){                System.out.println("id= " + rs.getInt("id"));                System.out.println("username= " + rs.getString("username"));                System.out.println("password= " + rs.getObject("password"));                System.out.println("======================================================");            }        } catch (SQLException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(conn, psta, rs);        }    }}

五、JDBC操作事务

和用sql执行事务类似,创建连接后setAutoCommit(false),最后commit(),失败则rollback()
注意:rollback()部分可以不用写,事务失败会自动回滚。

TestTransaction.java

package com.peng.less04;import java.sql.*;// 仍然使用前面写的JdbcUtils工具类import com.peng.less02.utils.JdbcUtils;public class TestTransaction {    public static void main(String[] args) {        Connection conn = null;        PreparedStatement pst = null;                try {            conn = JdbcUtils.getConnection();            // 关闭自动提交,开启事务            conn.setAutoCommit(false);            //模拟一个转账事务,A向大帅哥转账100块            String sql1 = "update account set `money`=money - 100 where `name`='A'";            pst = conn.prepareStatement(sql1);            pst.executeUpdate();            // int x = 1/0;            String sql2 = "update account set `money`=money + 100 where `name`='大帅哥'";            conn.prepareStatement(sql2).executeUpdate();            conn.commit();            System.out.println("Success!");        } catch (SQLException e) {            // TODO Auto-generated catch block            try {                // rollback()可以不用写,失败的话会自动回滚                conn.rollback();            } catch (SQLException e1) {                // TODO Auto-generated catch block                e1.printStackTrace();            }            e.printStackTrace();        }finally{            JdbcUtils.releaseConnection(conn, pst, null);        }    }}

点击全文阅读


本文链接:http://zhangshiyu.com/post/61244.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1