JDBC实现--保姆级教程~
本来以为写过一个使用python与数据库连接的文章,但是今天突然发现没有,那就直接写Java与数据库连接的吧。当然如果大家有需要可以告诉我,有时间的话也可以写一个的pymysql的使用的。
数据库有很多种,接下来我就以MySQL为例来进行讲解了,当然Java与其他数据库的连接也同样是这几步,因为他们都有同一个接口,见下
一.注册驱动
就是确定要使用哪个数据库
1.1下载驱动包
如果有对应jar包的就可以跳过这一步了
对应的地址在这里:MySQL驱动包下载地址
当然一般不建议使用最新版,旧版可以在Archives中找到
下载完成之后,解压
1.2添加jar包
打开解压过的文件,并找到上面标注的jar包
1.一般是可以直接放到你Java项目中的lib目录里面(如果找不到可以直接进行下面的第二步)
2.还需要在开发工具里把该 JAR 包添加到项目的类路径,这样 Java 虚拟机运行时才能找到它。
接下来需要在项目结构的模块中添加对应的jar包
直接在文件中找到之前你解压完成后,文件里对应的jar包就好了
1.3编写代码
// 1.注册驱动(确定要使用哪个数据库)
Class.forName("com.mysql.jdbc.Driver"); // 加载Driver类--在mysql5的驱动包之后,其实也可以省略// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 也可以这样,但是会有点显得多此一举(会重复注册两次)
二.连接数据库
就是要获取到一个数据库连接对象
// 2.连接数据库(获取到一个数据库连接对象)
final String URL = "jdbc:mysql://127.0.0.1:3306/demo1"; // :前可看作协议,数据库不同,协议不同
final String NAME = "root"; // 你数据库的用户名
final String PASSWORD = "1234"; // 你数据库的密码Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);
其实Connection与MySQL的事务也有关系,在这里我也就不过多赘述了,如果想继续扩充可以自己去查找资料,或在评论区滴我,后续有需要的我可以补充上噢
三.编写sql语句
一般建议先保证语句正确之后,再直接复制到代码中
这个也就不多说了,举个栗子
// 3.编写sql语句
String sql = "select * from tb_user;";
四.把sql语句发送给数据库
4.1实践
数据库执行sql代码,并返回执行结果
// 4.把sql语句发送给数据库(数据库执行sql代码,并返回执行结果)
Statement stmt = conn.createStatement(); // 基于数据库连接对象,创建一个操作数据库的对象// ①使用sql查找时
ResultSet rs = stmt.executeQuery(sql); // 把sql代码发给数据库// ②使用sql进行增删改操作时
int row = stmt.executeUpdate(sql); // 执行DML,DDL语句
// 执行DML语句时,执行后返回受影响行数 受影响行数为0表示增删改没有成功
// 执行DDL语句时,执行后返回0表示成功
4.2sql注入风险
但是使用Statement会有sql注入风险
例如,如果在上一步的password是这样的:
// 3.编写sql语句
String username = "aaa";
String password = "aaa' or 1=1-- ";// sql语句拼接时记得加空格(这里的?表示一个占位符)
String sql = "select * from tb_user where username = ? and password = ?;";
那么在使用Statement执行结果时,是一定会成功的,这时候对于数据库中的数据来说,就不是很安全了,所以在这个时候就有了PreparedStatement。而他其实也是Statement的一个子接口。
// 4.把sql语句发送给数据库(数据库执行sql代码,并返回执行结果)
// 创建预编译对象PreparedStatement pstmt = conn.prepareStatement(sql); // 基于数据库连接对象,创建一个操作数据库的对象// 给sql语句中的占位符赋值
pstmt.setString(1,username);
pstmt.setString(2,password);ResultSet rs = pstmt.executeQuery(); // 这里就不需要再传递内容了
其实PreparedStatement的作用也就相当于把敏感字符进行了一个转义,像'和--都把他们变成了字符串,而不是sql语句本身
一般来说建议使用:PreparedStatement,防止出错
五.处理sql的执行结果
注意区分查找和增删改其他操作的书写。
// 5.处理sql的执行结果(查询)
while(rs.next()){System.out.print(rs.getInt("id")+"\t");System.out.print(rs.getString("username")+"\t");System.out.println(rs.getString("password")+"\t");
}// 如果是增删改操作,就可以直接判断受影响的行数是多少来判断是否执行成功了
if(row > 0){System.out.println("数据操作成功");
}else{System.out.println("数据操作失败");
}
使用步骤:
1.游标向下移动一行,并判断该行是由有数据:next()
2.获取数据:getxxx(参数)
要注意,
1.获取到的数据是什么,就是get什么,例如说int-getInt,varchar-getString
2.而getxxx里面的参数,不管他之前的名字是什么,结果集上是什么就用什么来查询
因为在idea中返回的结果,是根据mysql中的执行结果来返回的
六.释放资源
断开和数据库的连接
// 6.释放资源(断开和数据库的连接)
rs.close();
stmt.close(); // 注意是pstmt还是stmt
conn.close();
就把所有打开的都关闭就是了,谁和谁的都不一样,关闭的顺序与你书写的顺序相反
就像我下面整体的代码,开启连接的顺序是:conn,stmt,rs。所以关闭的顺序就是rs,stmt,conn。
总:代码示例
下面代码我都是使用了@Test注解,大家也可以直接修改为main函数
基础代码:
package JDBC;import org.junit.Test;import java.sql.*;public class JbdcQuickStart {@Testpublic void quickStartTest() throws ClassNotFoundException, SQLException {
// 1.注册驱动(确定要使用哪个数据库)Class.forName("com.mysql.jdbc.Driver"); // 加载Driver类--在mysql5的驱动包之后,其实也可以省略
// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); 也可以这样,但是会有点显得多此一举(会重复注册两次)// 2.连接数据库(获取到一个数据库连接对象)String url = "jdbc:mysql://127.0.0.1:3306/demo1"; // :前可看作协议Connection conn = DriverManager.getConnection(url,"root","1234");// 3.编写sql语句String sql = "select * from tb_user;";// 4.把sql语句发送给数据库(数据库执行sql代码,并返回执行结果)Statement stmt = conn.createStatement(); // 基于数据库连接对象,创建一个操作数据库的对象ResultSet rs = stmt.executeQuery(sql); // 把sql代码发给数据库
// 5.处理sql的执行结果while(rs.next()){System.out.print(rs.getInt("id")+"\t");System.out.print(rs.getString("username")+"\t");System.out.println(rs.getString("password")+"\t");}// 6.释放资源(断开和数据库的连接)rs.close();stmt.close();conn.close();}
}
防止sql注入代码:
package JDBC;import org.junit.Test;import java.sql.*;public class SQL注入demo {// 使用PerparedStatement解决SQL注入问题@Testpublic void loginTest() throws ClassNotFoundException, SQLException {// 1.注册驱动(确定要使用哪个数据库)Class.forName("com.mysql.jdbc.Driver");// 2.连接数据库(获取到一个数据库连接对象)final String URL = "jdbc:mysql://127.0.0.1:3306/demo1";final String NAME = "root";final String PASSWORD = "1234";Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);// 3.编写sql语句String username = "aaa";String password = "aaa' or 1=1-- ";// sql语句拼接时记得加空格
// String sql = "select * from tb_user "+"where username = '小花' and password = '12345';";String sql = "select * from tb_user where username = ? and password = ?;";// 4.把sql语句发送给数据库(数据库执行sql代码,并返回执行结果)
// 创建预编译对象PreparedStatement pstmt = conn.prepareStatement(sql); // 基于数据库连接对象,创建一个操作数据库的对象// 给sql语句中的占位符赋值pstmt.setString(1,username);pstmt.setString(2,password);ResultSet rs = pstmt.executeQuery(); // 这里就不需要再传递内容了
// 5.处理sql的执行结果if (rs.next()) {String strname = rs.getString("username");String pwd = rs.getString("password");System.out.println("欢迎" + username + "登录");} else {System.out.println("登录失败!");}// 6.释放资源(断开和数据库的连接)rs.close();pstmt.close();conn.close();}
}
附加
其实我们对比代码可以发现,不管是什么操作,有几个步骤其实是不会改变的
这时候我们就可以把相似的代码合成一个包,以方便我们调用
接下来就直接给代码了
package JDBC.JDBC工具类的使用;/** 编写工具类:* 1.私有构造方法* 2.提供静态方法* */import java.sql.*;public class JdbcUtil {private static final String DRIVER = "com.mysql.jdbc.Driver";// 数据库连接参数(这是固定上了,按理说我感觉可以让他到时候自己设置)private static final String URL = "jdbc:mysql://127.0.0.1:3306/demo1";private static final String NAME = "root";private static final String PASSWORD = "1234";
// private static final String URL = "";
// private static final String NAME = "";
// private static final String PASSWORD = "";// 注册驱动(仅需1次)static {try {Class.forName(DRIVER);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}// 数据库连接public static Connection getConnection() throws SQLException {return DriverManager.getConnection(URL, NAME, PASSWORD);}// 释放资源(重载)public static void close(Connection conn, Statement stmt) {close(conn,stmt,null); // 方法重用}public static void close(Connection conn, Statement stmt, ResultSet rs) {try {if (rs != null) {rs.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if (stmt != null) {stmt.close();}} catch (SQLException e) {throw new RuntimeException(e);}try {if (conn != null) {conn.close();}} catch (SQLException e) {throw new RuntimeException(e);}}
}
总体就是这样啦,如果有什么问题可以随时在评论区提问噢~~~