1、JDBC
JDBC全称为:Java DataBase Connectivity(java数据库连接)。
SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。程序通过JDBC API连接到关系数据库,并使用结构化查询语句,完成对数据库的查询,更新等操作。
2、JDBC驱动程序
应用程序直接与JDBC相连接,数据库驱动程序把jdbc调用映射成特定的数据库。
大部分数据库系统都有相应的JDBC驱动程序,当需要某个连接时,必须有相应的数据库驱动。
Java数据库连接体系结构是用于Java应用程序连接数据库的标准方法。JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。作为API,JDBC为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。JDBC使用已有的SQL标准并支持与其它数据库连接标准,如ODBC之间的桥接。JDBC实现了所有这些面向标准的目标并且具有简单、严格类型定义且高性能实现的接口。
3、JDBC使用流程
1、通过DriverManager加载驱动程序driver;
第一种方式:基本不使用的方式
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
使用这种方式:registerDriver方法在mysql驱动中已经调用过了. 如果我们也调用相当于创建了两个驱动对象
第二种方式:常用的方式。
通过反射获取包名,不仅没有重复注册,而且容易修改包名。
Class.forName("com.mysql.jdbc.Driver");
2、通过DriverManager类获得表示数据库连接的Connection
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "123456");
获取连接的url
jdbc协议:数据库协议[:数据库的子协议]://主机名:端口号/库名?参数键1=参数值1&参数键2=参数值2
类对象;
3、通过Connection对象绑定要执行的语句,生成Statement类对象;
4、执行SQL语句,接收执行结果集ResultSet;
将查询(select语句)结果封装到resultSet对象中返回
Statement st = conn.createStatement();
//获得result对象
String sql = "select * from emp;";
// 执行sql语句获得
ResultSet rs = st.executeQuery(sql);
5、可选的对结果集ResultSet类对象的处理;
可以滚动的结果集.
resultset中的游标不仅仅可以通过next方法向下移动.也可任意移动位置.
例如以下方法:
rs.afterLast();//移动到最后一个之后
rs.previous();//游标向上移动一个
rs.absolute(1);//直接将游标移动到指定行
rs.beforeFirst();//移动到第一个之前
rs.first();//让游标移动到第一行
6、关闭资源(ResultSet、Statement和Connection)
保证 3个对象都要被释放掉resultset,statement,connection
try {
if(rs!=null){
rs.close();
}
} catch (Exception e) {
}finally{
try {
if(st!=null){
st.close();
}
} catch (Exception e2) {
}finally{
try {
if(conn!=null){
conn.close();
}
}catch (Exception e3) {
}
}
}
}
示例一:查询
package com.example.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
public class MyTest {
@Test
public void jdbcTest() throws Exception{
// 1、导包
// 2、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3、获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/student", "root", "123456");
// 4、发送sql语句
Statement state = conn.createStatement();
String sql = "select * from t_student;";
ResultSet rs=state.executeQuery(sql);
while(rs.next()){
String name = rs.getString("name");
System.out.println(name);
}
// 5、释放资源
rs.close();
state.close();
conn.close();
}
}
示例二:插入
@Test
public void jdbcTest2() throws Exception {
// 1、导包
// 2、注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 3、获得连接
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/student", "root", "123456");
// 4、发送sql语句
Statement state = conn.createStatement();
// String sql =
// "INSERT INTO `t_student`(`id`,`name`,`number`,`age`,`class`)VALUES('5','yu','10005',24,'数学');";
String sql = "INSERT INTO `t_student`(`NAME`,`number`,`age`,`class`)VALUES('tom4','1005',35,'英语');";
Boolean rs = state.execute(sql);
System.out.println(rs);// false表示插入成功
// 5、释放资源
state.close();
conn.close();
}
2、sql注入攻击
在以前开发中,登陆的逻辑是将用户提交的用户名和密码,拼接到sql语句中进行查询
如果查询成功,则表示用启登陆成功。
如果一些用户明白sql语句,那么就可以用一些特殊语句完成登陆的匹配条件
在数据库中创建两个用户名和密码
当用户提交用户名和密码的时候,sql语句的拼接如下
SELECT * FROM t_user WHERE NAME='yu' AND PASSWORD='123456';
但是如果用户提交的用户名是’yx’OR 1=1,密码123456时
就把这两条数据都查询出来了,也就表示都登陆了
代码如下
//sql注入的示例;
@Test
public void jdbcTest4() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///student",
"root", "123456");
Statement state = (Statement) conn.createStatement();
String name = "yu' OR 1=1 -- ";
String sql = "SELECT * FROM t_user WHERE NAME='"+name+"' and password='123456' ;";
ResultSet re = (ResultSet) state.executeQuery(sql);
while (re.next()) {
String n = re.getString("name");
String pa= re.getString("password");
System.out.println("name " + n + " password " + pa);
}
re.close();
state.close();
conn.close();
}
打印结果
name yxg age 123456
name yu age 123456
为了防止出现这样的情况在jdbc中提供这样一个对象,防止用户直接参数sql语句的拼接:预编译的PrepareStatement对象。
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.
PreparedStatement 实例包含已编译的 SQL 语句。这就是使语句“准备好”。包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。
//sql注入解决办法示例;
@Test
public void jdbcTest5() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///student",
"root", "123456");
String sql = "select * from t_user where name=? and password='123456' ;";
PreparedStatement pst = conn.prepareStatement(sql);
//String name = "yu' OR 1=1";
String name = "yu";
pst.setString(1, name);
ResultSet rs = pst.executeQuery();
while(rs.next()){
String n = rs.getString("name");
String pass=rs.getString("password");
System.out.println(n+"---"+pass);
}
rs.close();
pst.close();
conn.close();
}
1913

被折叠的 条评论
为什么被折叠?



