JDBC
Java DataBase Connectivity 是一个独立于特定数据库的管理系统,通用的SQL数据库存储和操作的公共接口。
定义了一组标准,为访问不同数据库提供了统一的途径
JDBC体系结构
JDBC接口包含两个层面:
- 面向应用的API,供程序员调用
- 面向数据的API,供厂商开发数据库的驱动程序
-
JDBC API
提供者: JAVA官方
内容:供开发者调用的接口- java.sql 和 javax.sql - DriverManager 类 - Connection接口 - Statement接口 - ResultSet 接口
-
JDBC Driver Manger
提供者:Java官方
作用:管理不同的JDBC驱动 -
JDBC驱动
提供者:数据库厂商
作用:负责连接不同的数据库
JDBC的使用
1、加载数据库驱动,java程序和数据库之间的桥梁
2、获取Connection,java程序与数据库的一次连接。
3、创建Statement对象,由Connection产生,执行SQL语句
4、如果需要接收返回值,创建ResultSet对象,保存Statement执行查询到的结果(查询才需要ResultSet对象)
public static void main(String[] args) {
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接,此处包含SSL和时区设置
String url = "jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";
String user= "root";
String password = "1234567";
Connection connection = DriverManager.getConnection(url,user,password);//url提供服务器、端口、数据库;user提供账号,password提供密码
System.out.println(connection);//打印出连接对象
String sql = "insert into student( name ,score,birthday) values('王五',60,'2019-01-11')";//添加操作
// sql = "delete from student";//删除操作
// sql = "update student set name = '李四'";//更新操作
Statement statement = connection.createStatement();//相当于通道语句
int result = statement.executeUpdate(sql);//增删改的执行语句
System.out.println(result);//返回修改的语句数量
// String sql = "select * from student";//查询操作
// Statement statement = connection.createStatement();//通道语句
// ResultSet resultSet = statement.executeQuery(sql);//查询所需的结果集
// while(resultSet.next())//循环输出
// {
// // Integer id = resultSet.getInt("id");
// String name = resultSet.getString(1);
// Double score = resultSet.getDouble(2);
// Date date= resultSet.getDate(3);
// System.out.println("-"+name+"-"+score+"-"+date);
// }
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e)
{
e.printStackTrace();
}
}
}
PreparedStatement
Statement 的子类,提供了SQL占位符的功能
使用Statement进行开发的两个问题:
1、需要频繁拼接String字符串,出错率较高。
2、存在SQL注入的风险
SQL注入:利用某些系统没有对用户输入的信息进行充分检测,在用户输入的数据中注入非法的SQL语句,从而利用系统的SQL引擎完成恶意行为的做法。
非法例子:
public class test {
public static void main(String[] args) {
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接,此处包含SSL和时区设置
String url = "jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";
String user= "root";
String password = "1234567";
Connection connection = DriverManager.getConnection(url,user,password);//url提供服务器、端口、数据库;user提供账号,password提供密码
System.out.println(connection);//打印出连接对象
String username = "李四";//
String mypassword = "xxxx' or '1'='1"; //最左补个‘,最后补个’ 形成非法语句
String sql = "select * from t_user where username ='"+username+ "' and password='"+mypassword+"'";
System.out.println(sql);
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql);
if(resultSet.next())
{
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e)
{
e.printStackTrace();
}
}
}
非法语句构成结果:
正确做法(PreparedStatement 提供占位符)
public class test {
public static void main(String[] args) {
try {
//加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接,此处包含SSL和时区设置
String url = "jdbc:mysql://localhost:3306/mytest?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";
String user= "root";
String password = "1234567";
Connection connection = DriverManager.getConnection(url,user,password);//url提供服务器、端口、数据库;user提供账号,password提供密码
System.out.println(connection);//打印出连接对象
String username = "李四";//
String mypassword = "xxxx' or '1'='1";
String sql = "select * from t_user where username = ? and password= ? ";
System.out.println(sql);
// Statement statement = connection.createStatement();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,username);
preparedStatement.setString(2,mypassword);
// ResultSet resultSet = statement.executeQuery(sql);
ResultSet resultSet = preparedStatement.executeQuery();
if(resultSet.next())
{
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch (SQLException e)
{
e.printStackTrace();
}
}
}
正确结果