JDBC
一.JDBC
1.概述:
Java DataBase Connectivity (Java 数据库连接)使用Java代码操作数据库JDBC其实就是一套操作数据库的规范(接口)
2.步骤:
a.导入驱动jar包b.注册驱动c.创建连接对象 Connectiond.定义SQL语句e.获取执行SQL的对象 Statementf.执行SQLg.处理结果h.释放资源
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Connection;
public class JDBC_Bulid {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1.导入数据数据库 jar包 右键add--->builderpath
// 2.加载驱动jar包
Class.forName("com.mysql.jdbc.Driver");
// 3.获取一个数据库链接对象
//参数1:数据库的路径 参数2,3 数据库的用户名和密码
String url = "jdbc:mysql://localhost:3306/demo01";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url, user, password);
// 4.获取操作对象 是同过连接对象去获取的
Statement statement = conn.createStatement();
// 5.定义sql语句
String sql = "insert into other values(3,'Hello','Y')";
// 6.执行语句
int i = statement.executeUpdate(sql);
if(i!=0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
// 7.释放资源
statement.close();
conn.close();
}
}
二.类的介绍
1.DriverManager(驱动管理类)
管理一组 JDBC 驱动程序的基本服务。a.功能1(注册驱动)
在Driver类中有静态代码块,随着类的加载而执行。static {
try {
java.sql.DriverManager.registerDriver(new Driver());//注册驱动
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}拓展:mysql5之后的驱动jar包,注册驱动这行代码可以省略
b.功能2(获取Connection对象)
public static ConnectiongetConnection(String url,String user,String password) throws SQLException试图建立到给定数据库 URL 的连接。DriverManager 试图从已注册的 JDBC 驱动程序集中选择一个适当的驱动程序。参数:
url- jdbc:subprotocol:subname 形式的数据库 urluser - 数据库用户,连接是为该用户建立的password - 用户的密码
注意:如果连接是本地数据库,则ip和端口号可以省略。
2.Connection(数据库连接对象)
java.sql接口 Connectiona.方法(创建执行SQL的对象):
i.createStatement() throws SQLException
创建一个 Statement 对象来将 SQL 语句发送到数据库。
ii.prepareStatement(String sql) throws SQLException
创建一个 PreparedStatement 对象来将参数化的 SQL 语句发送到数据库。
iii.prepareCall(String sql)throws SQLException
创建一个 CallableStatement 对象来调用数据库存储过程
b.管理事务:
事务指一件事,这一件事包含多个步骤,这些步骤要么同时成功,要么同时失败。
i.void setAutoCommit(boolean autoCommit) throws SQLException
将此连接的自动提交模式设置为给定状态。如果连接处于自动提交模式下,则它的所有 SQL 语句将被执行并作为单个事务提交。否则,它的 SQL 语句将聚集到事务中,直到调用 commit 方法或 rollback 方法为止。默认情况下,新连接处于自动提交模式。参数:autoCommit :
为 true 表示启用自动提交模式;
为 false 表示禁用自动提交模式
ii.voidcommit() throws SQLException
提交事务使所有上一次提交/回滚后进行的更改成为持久更改,并释放此 Connection 对象当前持有的所有数据库锁。此方法只应该在已禁用自动提交模式时使用。
iii.voidrollback() throws SQLException
取消在当前事务中进行的所有更改,并释放此 Connection 对象当前持有的所有数据库锁。此方法只应该在已禁用自动提交模式时使用。
3.Statement(执行sql的对象)
java.sql接口 Statement用于执行静态 SQL 语句并返回它所生成结果的对象。a.方法:
i.ResultSetexecuteQuery(String sql) throws SQLException
执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。返回值:
包含给定查询所生成数据的 ResultSet 对象;永远不能为 null
ii.intexecuteUpdate(String sql) throws SQLException
执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。返回值:
对于SQL数据操作语言(DML)语句,返回行计数(影响的行数)对于什么都不返回的SQL语句,返回 0
iii.booleanexecute(String sql) throws SQLException
执行给定的 SQL 语句,该语句返回执行的成功与否
4.ResultSet(结果集对象)
java.sql接口 ResultSetpublic interface ResultSet extends Wrapper表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。a.方法:
i.booleannext() throws SQLException
将光标从当前位置向前移一行。ResultSet 光标最初位于第一行之前;第一次调用 next 方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推
ii.参数类型 getXxx(参数):获取数据
参数类型:
String:列的名称int:列的序号 从1开始
5.PreparedStatement
public interface PreparedStatement extends Statement表示预编译的 SQL 语句的对象。SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。a.应用
登陆:
如果使用statement,可能发生sql注入。
功能:
预防sql注入
使用方式:
i.定义sql时,所有的参数位置 需要 使用 ? 作为占位符ii.Connection对象获取执行sql 对象 prepareStatement(sql)iii.给占位符 ? 赋值
setXxx(参数1,参数2):
- 参数1:?出现的位置 从1开始
- 参数2:?对应的值
iv.执行sql时,使用不带参数的方法注意:一般都采用该对象来执行sql
SQL注入演示:
此时的数据库:
此时的用户表:
在java代码中,把用户名和密码赋值成以下:
String name="1' or '1'='1";
String password="1' or '1'='1";
运行如下Java代码:
此时得到结果:package login; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCLogin { public static void main(String[] args) throws SQLException { // sql注入 通过一些特殊的拼字符串 绕过数据库的校验 String name = "1' or '1'='1"; String password = "1' or '1'='1"; Connection c = DriverManager.getConnection("jdbc:mysql:///day37", "root", "root");// 为了简洁这里抛出异常 // 获取SQL操作对象 Statement s = c.createStatement(); //定义SQL String sql = "select * from users where name='" + name + "' and password='" + password + "' ";//这里注意 单引号 和双引号的匹配问题 //执行 ResultSet resultSet = s.executeQuery(sql); //处理结果 if(resultSet.next()){ System.out.println("登陆成功"); }else{ System.out.println("登陆失败"); } //释放资源 c.close(); s.close(); resultSet.close(); } }
可以看出利用特殊的字符串的账号和密码组合绕过数据库进入
那么要防止这种情况发生,就得使用prepareStatement(sql)
防止SQL注入:
数据库和表还是上面的,不改变。
运行Java代码如下:
package login; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class JDBCLogin_SQLBuZhuRu { public static void main(String[] args) throws SQLException { String name="1' or '1'='1"; String password="1' or '1'='1"; // SQL 注入 通过一些特殊的拼字符串 绕过数据库的校验 Connection c = DriverManager.getConnection("jdbc:mysql:///day37", "root", "root"); // 获取预编译操作对象 String sql = "select * from users where name=? and password=?";//这里注意 账号 密码 用 ?代替 下面会赋值 PreparedStatement ps = c.prepareStatement(sql); //给?赋值 ps.setString(1, name); ps.setString(2, password); ResultSet resultSet = ps.executeQuery(); //执行查询 if(resultSet.next()){ System.out.println("登陆成功"); }else{ System.out.println("登陆失败"); } //释放资源 c.close(); ps.close(); resultSet.close(); } }
此时得到结果:
由此看出利用 Connection对象获取执行sql 对象 prepareStatement(sql),可以有效防止SQL注入。!