文章目录
数据库增删改查的实现
statement对象介绍
- Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通
过这个对象向数据库发送增删改查语句即可。 - Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,
executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变
化)。 - Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询
结果的ResultSet对象。
CRUD操作
CRUD操作-create
Statement st = conn.createStatement();
String sql = "insert into user(….) values(…..) ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println("插入成功!!!");
}
CRUD操作-update
Statement st = conn.createStatement();
String sql = “update user set name= ' ' where name= ' ' ";
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“修改成功!!!");
}
CRUD操作-delete
Statement st = conn.createStatement();
String sql = “delete from user where id=1”;
int num = st.executeUpdate(sql);
if(num>0){
System.out.println(“删除成功!!!");
}
CRUD操作-read
Statement st = conn.createStatement();
String sql = “select * from user where id=1;
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
//根据获取列的数据类型,分别调用rs的相应方法映射到java对象中
}
优化实验环境
- 利用properties文件存储数据库信息
内容包括创建连接时所需要的驱动,数据库的用户名和密码,以及url
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/studyjdbc
username=root
password=123456
- 编写一个工具类负责创建连接和关闭数据库资源 .
利用Junit测试增删改查
- 在包中建立db.properties文件,利用该文件存储数据库信息,文件内容如下
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/studyjdbc
username=root
password=123456
- 建立工具类Util,在概包中建立工具类。
package com.westos.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
//编写一个工具类简化开发 , 创建连接数据库都是死代码 , 每次写及其不方便 , 还有关闭连接;
public class JDBCUtils {
private static String driver=null;
private static String username=null;
private static String password=null;
private static String url=null;
static{
try {
//加载配置文件
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(is);
//读取配置文件
driver = properties.getProperty("driver");
username = properties.getProperty("username");
password = properties.getProperty("password");
url = properties.getProperty("url");
//加载数据库驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取数据库连接对象
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//释放资源
public static void closeAll(ResultSet resultSet, Statement statement,Connection connection){
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();
}
}
}
}
- 利用JDBCUtil工具类,可以测试JDBC的CRUD操作
package com.westos.dao;
import com.westos.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
//测试JDBC的CRUD
public class Demo01 {
@Test
public void insert() {
Connection connection = null;
Statement statement = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.创建statement对象
statement = connection.createStatement();
//3.编写Sql语句
String sql = "INSERT INTO users(id,NAME,PASSWORD,email,birthday) VALUES(5,'wangwu','123456','wangwu@sina.com','1979-12-04');";
//4.执行sql语句
int i = statement.executeUpdate(sql); //返回受影响的行数
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
JDBCUtils.closeAll(null,statement,connection);
}
}
@Test
public void delete() {
Connection connection = null;
Statement statement = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.创建statement对象
statement = connection.createStatement();
//3.编写Sql语句
String sql = "delete from users where id = 5";
//4.执行sql语句
int i = statement.executeUpdate(sql); //返回受影响的行数
if (i>0){
System.out.println("删除成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
JDBCUtils.closeAll(null,statement,connection);
}
}
@Test
public void update() {
Connection connection = null;
Statement statement = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.创建statement对象
statement = connection.createStatement();
//3.编写Sql语句
String sql = "update users set name = 'qinjiang' where id = 4";
//4.执行sql语句
int i = statement.executeUpdate(sql); //返回受影响的行数
if (i>0){
System.out.println("修改成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
JDBCUtils.closeAll(null,statement,connection);
}
}
@Test
public void query() {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.创建statement对象
statement = connection.createStatement();
//3.编写Sql语句
String sql = "select * from users";
//4.执行sql语句
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getInt("id"));
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
System.out.println(resultSet.getString("email"));
System.out.println(resultSet.getDate("birthday"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
JDBCUtils.closeAll(resultSet,statement,connection);
}
}
}
SQL注入
SQL注入问题
我们发现,按照上面的方法进行操作,无论密码是否正确,都提示我们登陆成功,这显然是不
合理的。问题出在哪里呢?
字符串拼接后的SQL语句是:
select * from users where username = 'kuangshen' or 1 = 1 and password = '"+password+"';
运行到or的时候已经是条件成立,所以无论后面是否正确,无需验证密码即可登陆成功。
上面的问题都是通过在SQL语句中添加特殊的字符,构成关键字,改变了程序运行轨迹,从而
对数据进行操作。
SQL注入问题:是指通过客户输入到后台的那些能到数据库得到数据的位置上,恶性的输入一些
对数据有害的操作。(就是通过把SQL命令插到Web表单提交,最终达到欺骗服务器执行恶意的SQl命令)
package com.westos.dao;
import com.westos.utils.JDBCUtils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//1.获取数据库连接
connection = JDBCUtils.getConnection();
//2.创建statement对象
statement = connection.createStatement();
//3.编写Sql语句
//如果输入数据库表单中有的用户名,可以获得正确的结果
//若果输入不存在的用户名,查询会失败
System.out.print("请输入你要查询的用户名:");
String username = scanner.nextLine();
String sql = "select * from users where name = " + username;
System.out.println(sql);
//select * from users where name = qinjiang or 1=1;
resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println(resultSet.getString("name"));
System.out.println(resultSet.getString("password"));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//5.释放资源
JDBCUtils.closeAll(resultSet,statement,connection);
}
}
}
PreparedStatement对象
PreparedStatement对象介绍
- PreperedStatement是Statement的子类
- 它的实例对象可以通过调用Connection.preparedStatement()方法获得,相对于Statement对象
而言:PreperedStatement可以避免SQL注入的问题。 - Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对
SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数,
允许使用占位符的形式进行替换,简化sql语句的编写。
PreparedStatement对象和Statement的区别
相同点 :
- 都是用来执行sql语句的
不同点 :
- Statement 不安全 , 不能预编译SQL , 不能使用占位符 , 容易造成SQL语句拼接错误,不能防止SQL注入攻击
- preparedStatement 安全 ,可以防止SQL注入攻击,可以预编译SQL语句 , 可以使用 ?作为占位符 。
- Statement 先写SQL语句再执行;
- preparedStatement 直接编译SQL , 调用方法执行 ; preparedStatement.execute()