11、数据库驱动和JDBC
1. 第一个JDBC程序
1️⃣ 新建空项目
2️⃣ 导入mysql-connector-java
在项目目录下新建lib
目录,放入jar包
3️⃣ 编写代码&测试
package com.itheima;
import java.sql.*;
public class JDBCDemo {
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/mydb?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC";
String username = "root";
String password = "123456";
//3.链接,获得数据库对象connection
Connection connection = DriverManager.getConnection(url, username, password);
//4.获得执行sql的对象
Statement statement = connection.createStatement();
//5.执行sql
String sql = "select * from student";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("id:" + resultSet.getObject("sid") + "sname:" + resultSet.getObject("sname"));
}
//6.释放链接
resultSet.close();
statement.close();
connection.close();
}
}
运行结果:
2. JDBC对象
DriverManager
DriverManager:驱动管理
//1.加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
本质上执行DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
//3.连接,获得数据库对象connection
Connection connection = DriverManager.getConnection(url, username, password);
connection
代表数据库,因此可以设置事务自动提交,事务回滚等
Statement
Statement:执行sql的对象,用于向数据库发送SQL语句,想完成对数据库的增删改査,只需要通过这个对象向数据库发送增删改查语句即可
statement.executeQuery();//查询操作,返回结果
statement.execute();//执行sql
statement.executeUpdate();//用于增删改,返回受影响的行数
CRUD操作-create
ResultSet
3. 封装jdbc工具类
1. 编写数据库配置文件
在resources
目录下新建db.properties
,用于存放数据库配置信息
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC
username=root
password=123456
2. 编写工具类
然后再src
目录下新建JDBCUtils.java
作为工具类
package com.itheima;
import com.itheima.JDBCDemo;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JDBCUtils {
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
static {
try {
InputStream inputStream = JDBCDemo.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(inputStream);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//加载驱动
Class.forName(driver);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//释放连接资源
public static void release(Connection connection, Statement statement, ResultSet resultSet){
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3. 测试
修改JDBCDemo
package com.itheima;
import java.sql.*;
public class JDBCDemo {
public static void main(String[] args) throws SQLException {
//获得数据库对象connection
Connection connection = JDBCUtils.getConnection();
//获取sql执行对象:statement
Statement statement = connection.createStatement();
//执行sql
String sql = "select * from student";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("sid:" + resultSet.getObject("sid") + "sname:" + resultSet.getObject("sname"));
}
//释放连接
JDBCUtils.release(connection,statement,resultSet);
}
}
运行结果:
4. SQL注入问题
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
sql注入案例:主函数中传入用户名,查找指定名字用户信息
package com.itheima;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestTransaction {
public static void main(String[] args) throws SQLException {
searchName("'张三'");
}
//查找指定名字用户信息
public static void searchName(String username) throws SQLException {
//获取数据库对象connection
Connection connection = JDBCUtils.getConnection();
//获取sql执行对象statement
Statement statement = connection.createStatement();
//执行sql
String sql = "select * from student where sname="+username;
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("sid:"+resultSet.getObject("sid")+"sname:"+resultSet.getObject("sname"));
}
//释放连接
JDBCUtils.release(connection,statement,resultSet);
}
}
运行结果:
sid:1sname:张三
这里传入的是用户名
拼接整条sql语句是select * from studentwhere name='张三 ' ,z这就是SQL注入,需要小心!!!
5. PreparedStatement对象
同样测试sql注入案例
package com.itheima;
import java.sql.*;
public class TestTransaction {
public static void main(String[] args) throws SQLException {
searchName("'张三'");
}
//查找指定名字用户信息
public static void searchName(String username) throws SQLException {
//获取数据库对象connection
Connection connection = JDBCUtils.getConnection();
//获取sql执行对象statement
PreparedStatement preparedStatement = connection.prepareStatement("select * from student where sname=?");
//手动传参
preparedStatement.setString(1,username);
//执行sql
ResultSet resultSet = preparedStatement.executeQuery();
while (resultSet.next()){
System.out.println("sid:"+resultSet.getObject("sid")+"sname:"+resultSet.getObject("sname"));
}
//释放连接
JDBCUtils.release(connection,preparedStatement,resultSet);
}
}
运行结果:
根据结果,PreparedStatement对象完美避免了sql注入问题
6. 事务案例
首先创建account表
CREATE TABLE account(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(40),
money FLOAT
);
INSERT INTO account(name,money) VALUES('A',1000);
INSERT INTO account(name,money) VALUES('B',1000);
INSERT INTO account(name,money) VALUES('C',1000);
然后编写Java代码
package com.itheima;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestTransaction {
public static void main(String[] args) throws SQLException {
//获取数据库对象connection
Connection connection = JDBCUtils.getConnection();
//关闭数据库自动提交,即开启事务
connection.setAutoCommit(false);
String sql1 = "UPDATE account SET money = money+100 WHERE name = 'A'";
String sql2 = "UPDATE account SET money = money-100 WHERE name = 'B'";
//获取sql执行对象preparedStatement
PreparedStatement preparedStatement = connection.prepareStatement(sql1);
preparedStatement.executeUpdate();
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();
//业务完毕,提交事务
connection.commit();
//释放资源
JDBCUtils.release(connection,preparedStatement,null);
}
}
运行结果:
如果两次更新之间加int x = 1 / 0; 则会报错,且事务执行失败,两条语句都不会执行成功
————————————————