1.Statement
1.1 具体步骤
1.注册驱动
2.获取连接
3.创建发送sql语句对象
4.发送sql语句并得到返回结果
5.对得到的结果集进行解析
6.释放资源(包括结果集 连接 驱动)
1.2 简单实例
数据库中当前存在以下数据:
//创建数据库连接 模拟用户输入用户名和密码 在数据库中查询该用户是否存在 如果存在则输出用户信息
public class statementQuery {
public static void main(String[] args) throws SQLException {
//用户输入账号和密码
Scanner scanner = new Scanner(System.in);
String account = scanner.nextLine();
String password = scanner.nextLine();
scanner.close();
//1.注册驱动
DriverManager.registerDriver(new Driver());
//2.创建连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigu", "root", "123456");
Statement statement = connection.createStatement();
//3.创建发送sql语句对象
String sql = "select * from t_user where account = '" + account + "' and password = '" + password + "' ;";
//4.发送sql语句并得到返回结果
ResultSet resultSet = statement.executeQuery(sql);
//5.结果集解析
if (resultSet.next()) {
int id = resultSet.getInt("id");
String account1 = resultSet.getString("account");
String password1 = resultSet.getString("password");
String nickname = resultSet.getString("nickname");
System.out.println("id:" + id + " account:" + account1 + " password:" + password1 + " nickname :" + nickname);
} else {
System.out.println("用户不存在");
}
//6.关闭资源
resultSet.close();
statement.close();
connection.close();
}
}
1.3 对核心API的解释说明
1.注册驱动
使用 DriverManager.registerDriver(new Driver());会注册两次驱动,造成不必要的资源浪费
使用反射的方法进行驱动注册: Class.forName("com.mysql.cj.jdbc.Driver");
2.获取连接(3种方法)
url:连接数据库的地址(形式如下所示)
jdbc:数据库类别://IP地址:端口号/数据库名
jdbc:mysql://127.0.0.1:3306/atguigu
jdbc:mysql://localhost:3306/atguigu (127.0.0.1=localhost)
jdbc:mysql:///atguigu (IP地址是当前电脑且端口号是3306时可以这样写)
user:连接数据库用户名
password:连接数据库密码
2.1 getConnection(String url,String user, String password)
getConnection("jdbc://localhost:3306/atguigu","root","123456");
2.2 getConnection(String url,java.util.Properties info)
Properties : 是一个参数封装容器!至少要包含 user / password 存储连接账号信息
Properties properties=new Properties();
properties.put("user","root");
properties.put("password","123456");
getConnection("jdbc://localhost:3306/atguigu",properties);
2.3 getConnection(String url)
URl可以携带目标地址,可以通过?分割,在后面key=value&key=value形式传递参数
getConnection("jdbc://localhost:3306/atguigu?user=root&password=123456");
3. 发送sql语句并得到查询结果
3.1 ResultSet executeQuery(String sql)
其中sql只能是DQL,对数据库进行查询,返回的是封装的结果集对象
3.2 int executeUpdate(String sql)
3.2.1 sql是DML语句 返回影响的行数,如修改2条则返回2,删除1条则返回1
3.2.2 sql语句是非DML非DQL语句,返回值始终是0
5. 对结果进行解析
get类型(int columnIndex | String columnLabel)
columnLabel:如果没有别名,等于列名,有别名就是别名
columnIndex:从左到右 从1开始
int id = resultSet.getInt(1); = int id = resultSet.getInt("id");
String account1 = resultSet.getString(2); = String account1 = resultSet.getString("account");
String password1 = resultSet.getString(3); = String password1 = resultSet.getString("password");
String nickname = resultSet.getString(4); = String nickname = resultSet.getString("nickname");
2. PreparedStatement
- Statement 安全隐患—注入攻击
Statement 在执行 sql 语句时都会把表单提交来的 用户名 和 密码 都重新拼接到 sql 语句中,然后再执行,这样会导致 sql 语句结构发生改变。
String sql = "select * from t_user where account = '" + account + "' and password = '" + password + "' ;";
当登录的时候用户输入 1' OR '1'='1 也可以登陆成功,此时sql变成如下所示:
sql = "select * from t_user where account = '" + account + "' and password = '1' OR '1'='1' ;";
此时会将原表中所有的信息都查询到,因为where后面的子句是true,如果按照Statement中的代码,最终会输出第一行数据信息。
- 占位符如何避免了注入攻击
当使用占位符时,数据库引擎会将查询和提供给占位符的值视为两个分离的部分。
SELECT * FROM users WHERE username = ?
若用户恶意输入’admin’ OR 1=1。假如不使用占位符,则SQL语句如下
SELECT * FROM users WHERE username = 'admin' OR 1=1'
1=1恒为真,数据库会返回所有的user行,因为数据库将1=1视为bool值进行了判断。但是若使用了占位符,数据库会将所有的输入视为普通的文本输入,而不会进行bool值判断,即不再会判断1=1是否为真,而是只是将其视为简单的文本输入。
2.1 具体步骤
注意与Statement的区别在于3456,先编写sql语句结构并传给PerparedStatement保证了结构的确定性,可以避免出现注入攻击
1.注册驱动
2.建立连接
3.编写动态sql语句结构,动态值使用 ? 代替
4.创建PerparedStatememt,并传入动态sql语句
5.给动态值赋值
6.发送sql语句并获得返回结果
7.对返回结果集进行解析
8.释放资源(包括结果集、连接、驱动)
2.2 简单实例
//创建数据库连接 模拟用户输入用户名和密码 在数据库中查询该用户是否存在 如果存在则输出用户信息
public void testQuery() throws Exception {
Scanner scanner = new Scanner(System.in);
String account = scanner.nextLine();
String password = scanner.nextLine();
scanner.close();
//1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.创建连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu?user=root&password=123456");
//3.编写动态sql结构
String sql = " select * from t_user where account=? and password=?;";
//4.创建PerparedStatement并传入sql
java.sql.PreparedStatement preparedStatement = connection.prepareStatement(sql);
//5.占位符赋值
preparedStatement.setObject(1, account);
preparedStatement.setObject(2, password);
//6.执行sql语句并拿到结果集
ResultSet resultSet = preparedStatement.executeQuery();
//7.对结果集进行解析
if (resultSet.next()) {
int id = resultSet.getInt(1);
String account1 = resultSet.getString(2);
String password1 = resultSet.getString(3);
String nickname = resultSet.getString(4);
System.out.println("id:" + id + " account:" + account1 + " password:" + password1 + " nickname :" + nickname);
} else {
System.out.println("用户不存在");
}
//8.关闭资源
resultSet.close();
preparedStatement.close();
connection.close();
}
//插入一条数据
public void testInsert() throws Exception {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu?user=root&password=123456");
String sql="insert into t_user(account,password,nickname) values(? ,?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1,"zhangsan");
preparedStatement.setObject(2,"999999");
preparedStatement.setObject(3,"员工");
int resultSet = preparedStatement.executeUpdate();
if(resultSet>0){
System.out.println("插入数据成功");
}else {
System.out.println("插入数据失败");
}
preparedStatement.close();
connection.close();
}