Jdbc (java database connection) java 数据库连接
Java.sql包下面
Java本身提供了一套数据库操作的接口,然后由数据库厂商去实现该接口进行数据库操作
这些接口的实现都由数据库厂商去完成。Java操作数据库单独时候就可以加上这个驱动就可以操作数据库了。
所以本来是这样的,其实java本身是不能操作数据库的,需要数据库厂商去帮助实现接口,因为数据库厂商实在太多了,必须帮助实现java的接口,java才能操作数据库。下面以mysql为例来写一个实例
在操作mysql的时候要提供一个mysql的数据库驱动(就是一个jar包)
这里用的软件是Eclipse,具体怎么导入驱动包,以及驱动包的下载,由于我一直在赶进度,所以劳烦各位自己百度解决下。我这里还用到了数据库的可视化图形工具Sqlyog,当然了你也可以用Navicat,在我们学习的时候可以用破解版,但是当我们有收入以后还是希望各位支持正版。毕竟都是作为开发者,都是靠这个吃饭的。这里也劳烦各位自己找下资源。
首先书写代码:代码我基本都打上注释了。而后补充一下resultSet.next()
,这个东西返回的是一个boolean值,比如select * from User
,表数据如下:
JDBC.java
package mysql_jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* @author Hercules
* @version 创建时间:2020年6月12日 下午3:35:06
* 类说明
*/
public class JDBC {
public static void main(String[] args) {
//jdbc操作步骤
//1 加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection conn = null;
Statement statement = null;
ResultSet resultSet = null;
//获取连接
try {
//1 链接的数据库localhost:3306表示本机的3306端口 test表示数据库名
//2 root数据库账号
//3 root数据库密码
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root");
//连接不为null就表示和数据库链接成功了
//书写sql语句
String sql = "select * from User";
//3获取处理器
statement = conn.createStatement();
//4获取结果集
resultSet = statement.executeQuery(sql);
//5处理结果集
while(resultSet.next()) {//循环行
String username = resultSet.getString("username");
String password = resultSet.getString("password");
int power = resultSet.getInt("power");
System.out.println(username + "=" + password + "=" + power);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {//最后要关闭资源
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
最后输出结果如下:
在这里while循环中的代码还可以修改如下:
while(resultSet.next()) {//循环行
String username = resultSet.getString(1);
String password = resultSet.getString(2);
int power = resultSet.getInt(3);
System.out.println(username + "=" + password + "=" + power);
}
运行结果是一样的:
这里注意,sql的下标是从1开始的并不是从0开始的。
这时候比如用jdbc实现修改赵朔的权限值为2。
比如将sql修改如下:
//先给方法加一个参数:
public static void statementcud(String username)
//而后调用的时候给username变量传入"赵朔"
//username在这里就是一个变量
String sql = "update user set power=2 where username='"+username+"'";
不过下面就不能调用executequery了,要调用executeUpdate();
最后返回的是int类型的变量:
如下:
int result = statement.executeUpdate(sql);
这里int类型的变量的意思是影响了多少行数据的意思。
也就是只要这个变量大于0就表示执行成功。
最后再补充一下delete,insert,和update都是类似调用executeUpdate方法
下面来看一个问题
就是上面的一行代码:
String sql = "update user set power=2 where username='"+username+"'";
这个username是一个变量应该是用户传入的。但是假如现在有一个懂程序的用户,注意这种用户肯定不在少数的。这年头首先计算机相关专业的烂大街了。其次好多人看上了这个行业,纷纷转行。
假如有一个人将username这个变量这么写:
赵朔';delete from user where 1=1 or 1='1
假如这个语句真的传入进去会发生什么?
那么这个表里面的所有数据都会被删除,目前对于互联网公司而言,数据是最重要的资产,如果用户传入参数如下,造成的损失是不可估量的。
这种情况称为sql注入攻击,Statement是无法避免的。意味着statement是不安全的。
为了避免这种情况需要使用预处理器也就是如下代码:
/**
* 预处理器处理查询
*/
public static void preparedStatementquery(String name) {
//jdbc操作步骤
//1 加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2 获取连接
Connection conn = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 1 连接的数据库 localhost:3306 表示本机的3306端口 test表示数据库名
// 2 root数据库账号
// 3 root 数据库密码
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
//连接不为null就表示和数据库连接成功了
String sql = "select * from user where username=?";
//3 获取预处理器 就需要将sql传入
statement = conn.prepareStatement(sql);
//注入值 从1开始
statement.setString(1, name);
//4获取结果集
resultSet = statement.executeQuery();
//5 处理结果集
// while(resultSet.next()) {//循环行
// String username = resultSet.getString("username");
// String password = resultSet.getString("password");
// int power = resultSet.getInt("power");
// System.out.println(username + "=" + password + "=" + power);
// }
while(resultSet.next()) {//循环行
//如果使用下标的方式也可以获取,但是jdbc里面下标是从1开始的
String username = resultSet.getString(1);
String password = resultSet.getString(2);
int power = resultSet.getInt(3);
System.out.println(username + "=" + password + "=" + power);
}
} catch (SQLException e) {
e.printStackTrace();
} finally{
//6关闭资源
if(resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
这里对于代码有必要解释一下:
首先第一行sql
String sql = “select * from user where username=?”;
这里?就是变量,无论用户传什么东西进去,这里始终会把?的部分当成username的值。
而后看下面四句:
//连接不为null就表示和数据库连接成功了
String sql = "select * from user where username=?";
//3 获取预处理器 就需要将sql传入
statement = conn.prepareStatement(sql);
//注入值 从1开始
statement.setString(1, name);
//4获取结果集
resultSet = statement.executeQuery();
第二句是将sql传入预处理器,但是这时候?没有值,则需要注入值,这里是根据?的顺序进行值的注入,第一个?注入值name变量。最后再获取结果值。所以这样不管再受到怎样的sql注入攻击。
而后不是查询了,是增删改的信息:
/**
* 预处理器处理增删改
*/
public static void preparedStatementcud(String username) {
//jdbc操作步骤
//1 加载驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//2 获取连接
Connection conn = null;
PreparedStatement statement = null;
try {
// 1 连接的数据库 localhost:3306 表示本机的3306端口 test表示数据库名
// 2 root数据库账号
// 3 root 数据库密码
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
//连接不为null就表示和数据库连接成功了
String sql = "update user set power=? where username=?";
//delete , insert 和update都是类似调用 executeUpdate 方法
//3 获取处理器
statement = conn.prepareStatement(sql);
//注入值 数字为第几个问号? 从1开始
statement.setInt(1, 3);
statement.setString(2, username);
//4获取影响行数
int result = statement.executeUpdate();
//5 处理结果集
System.out.println(result + "大于0即表示执行成功");
} catch (SQLException e) {
e.printStackTrace();
} finally{
//6关闭资源
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
主要的代码在于以下几行代码:
//连接不为null就表示和数据库连接成功了
String sql = "update user set power=? where username=?";
//delete , insert 和update都是类似调用 executeUpdate 方法
//3 获取处理器
statement = conn.prepareStatement(sql);
//注入值 数字为第几个问号? 从1开始
statement.setInt(1, 3);
statement.setString(2, username);
//4获取影响行数
int result = statement.executeUpdate();
第一个问号是int类型的所以传入了一个int类型的变量。也就是setInt方法,而username是String类型的所以用setString方法。而set类型(),的第一个参数就是第几个问号。而后最后就得到影响的行数。
预处理器会将sql语句预编译存入当前对象中,确认该sql只能做什么事情,即使有sql注入攻击,也不会执行。可以防止sql注入攻击。所以作为平常项目中的编码来说,都用预处理器。说白了就是建议大家使用预处理器不建议使用处理器。