目录
JDBC概括
JDBC(Java与数据库连接):Java DataBase Connectivity
此技术是Java提供的一种数据库操作技术,提供了统一标准,但是此技术不在JDK中,需要下载相应的JAR包。
JAR包:其他人写好的类打包
JAR包下载使用
下载::https://mvnrepository.com/搜索mySQL
使用步骤:
1,在项目的根目录下创建文件夹,这个文件夹必须命名为lib
2,将需要使用的jar包拷贝到lib文件夹下
3,选择jar包,点击右键选择add as libxxx
JDBC的操作步骤
粗略步骤
1,加载驱动,反射的技术
一个进程一次就行
Class.forName("驱动类所在的包名.类名");
如果不写的话也可以运行成功,这是因为JDBC4.0以后新增了新特性:JDBC4.0不再需要显式调用class.forName()注册驱动,DriverManager初始化中会通过ServiceLoader类,在我们classpath中jar(数据库驱动包)中查找,使用META-INF\services\java.sql.Driver文本中的类名称去注册。
2,创建连接
通过DriverManager建立连接
Connection c = DriverManger.getConnection(数据库url,数据库账号, 数据库密码)
3,获取sql语句执行对象
//存在sql注入问题 Statement s = c.createStatement();
//解决了sql注入问题 PreparedStatement s = c.prepareStatement(sql);
4,执行sql语句
//用于执行DML操作,返回值时受影响行数 int num = s.executeUpdate();
//用于执行DQL操作,返回值时查询到的结果 ResultSet set = s.executeWQuery();
5,处理结果
根据需求处理
6,关闭资源
如果执行的时查询操作需要关闭查询结果集
关闭sql语句执行
关闭连接对象
JDBC操作核心类:
DriverManger:驱动管理器
作用:获取连接
提供的静态方法方法: Connection getConnection(url,username,password);
Class.forName("com.mysql.jdbc.Driver");//使用反射获取类对象
Connection connection = DriverManager.getConnection(URL, USER, PASSMI);
//使用getConnection方法,驱动管理,获取连接
URL:
例
String URL = "jdbc:mysql://localhost:3306/zday0301?useSSL=false&characterEncoding=utf-8";
url要写服务器地址和端口号,表名
useSSL=false和true的区别:
SSL(Secure Sockets Layer 安全套接字协议),useSSL=false通过账号 密码进行连
接,跳过安全验证。useSSL=true是进行安全验证,mysql的版本是5.7之前会默
认useSSL=false。之后包括5.7则不会,为了能连接上使用useSSL=false。
USER:数据库账号
USER = "root";
PASSMI:数据库密码
PASSMI= "123456"
Connection:数据库连接对象
作用:获取sql语句执行对象,执行事物
注意:默认自动提交
提供的方法:
Statement createStatement(); //有sql注入风险
PreparedStatement prepareStatement(sql); //解决了sql注入风险
CallableStatement prepareCall(String sql); //用于调用存储过程
void rollback();//回滚
void commit();//提交
c.setAutoCommit(false);设置是否自动添加,默认为true //
void setAutoCommit(boolean autoCommit); 关闭自动条件并开启事物
Statements:sql语句执行
作用:执行sql语句
提供的方法:
1. int executeUpdate():用于执行DML操作 数据的增加或删除
返回值为int型,为多少行受到了影响
2.ResultSet executeWQuery():用于执行DQL操作 数据的查询
ResultSet 包含符合 SQL 语句中条件的所有行,并且它通过一套 get 方法(这些 get 方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next 方法用于移动到 ResultSet 中的下一行,使下一行成为当前行,此方法是从表头开始移动的
3.boolean execute():用于执行DDL操作
Statements 的 子类: PreparedStatement
作用:解决sql注入问题
提供的方法:
setInt(?号的位置,替换?号的值);
setString(?号的位置,替换?号的值);
...
注意:?表示占位符,位置从1开始
Statements 子类: CallableStatement
作用:调用存储过程
ResultSet:结果查询
作用:存储查询的结果
提供的方法:
boolean next():移动游标
getInt(列名);
getString(列名);
sql注入
概述
程序对用户输入数据的合法性没有判断和处理,导致用户可以在应用程序中事先定义好的 SQL 语句中添加额外的 SQL 语句,以此来实现欺骗数据库服务器,来执行非任意查询语句。
例:恶意拼接查询
SELECT * FROM users WHERE user_id = $user_id
其中,$user_id 是传入的参数,
如果传入的参数值为“1234; DELETE FROM users”,
那么最终的查询语句会变为:
SELECT * FROM users WHERE user_id = 1234; DELETE FROM users
如果以上语句执行,则会删除 users 表中的所有数据。
解决
参数化查询:
参数化查询目前被视作是预防 SQL 注入攻击最有效的方法。参数化查询是指在设计与数据库连接并访问数据时,在需要填入数值或数据的地方,使用参数(Parameter)来给值。
MySQL 的参数格式是以“?”字符加上参数名称而成,如下所示:
UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4
在使用参数化查询的情况下,数据库服务器不会将参数的内容视为 SQL 语句的一部分来进行处理,而是在数据库完成 SQL 语句的编译之后,才套用参数运行。因此就算参数中含有破坏性的指令,也不会被数据库所运行。
例子:
做一个使用数据库登录注册功能
import java.sql.*;
import java.util.Scanner;
public class Main {
static {//静态只在类加载时加载一次
try {
Class.forName("com.mysql.jdbc.Driver");
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}//加载驱动
private static final String URL = "jdbc:mysql://localhost:3306/zday0301?useSSL=false&characterEncoding=utf-8";
//url要写服务器地址和端口号,表名
private static final String USER = "root";//数据库账号 上面的useSSL=false跳过安全验证,
private static final String PASSMI= "123456";//数据库密码
public static void main(String[] args) throws SQLException {
login();
// regisr();//调用两个方法
}
public static void regisr() throws SQLException {
System.out.println("输入账号");
Scanner scanner = new Scanner(System.in);
String usrname = scanner.next();
System.out.println("输入密码");
String mima = scanner.next();
System.out.println("输入性别");
String sex = scanner.next();
System.out.println("输入年龄");
String age = scanner.next();
Connection connection = DriverManager.getConnection(URL, USER, PASSMI);//驱动管理,获取连接
Statement statement = connection.createStatement();//获取sql语句执行对象,执行事物
String sql = "select u_username from yinhang where u_username='"+usrname+"'";//查询语句
ResultSet set = statement.executeQuery(sql);//执行DQL操作
//这东西返回的结果是个集合
if (set.next()){//向下移动,从表头开始的,如果不能移动的那就一个数据都没有,能移动表名可移动,说明有重复的
System.out.println("账号以存在");
return;
}
String intoSQL = "insert into yinhang (u_username,u_mima,u_sex,u_age)values('"+usrname+"','"+mima+"','"+sex+"',"+age+")";//插入语句
int i = statement.executeUpdate(intoSQL);//向里面插入数据,执行
if (i>0){
System.out.println("注册成功");
}else {
System.out.println("注册失败");
}
if (statement != null&&!statement.isClosed()){//不判断的话会空指针异常
statement.close();
}
if (connection != null && !connection.isClosed()){
connection.close();
}
}
public static void login() throws SQLException {
System.out.println("输入账号");
Scanner scanner = new Scanner(System.in);
String usrname = scanner.next();
System.out.println("输入密码");
Scanner scanner2 = new Scanner(System.in);
String mima = scanner2.next();
Connection connection = DriverManager.getConnection(URL, USER, PASSMI);//驱动管理,获取连接
PreparedStatement statement = connection.prepareStatement( "select u_username from yinhang where u_username = ? and u_mima = ?");
statement.setString(1,usrname);//前面的参数代表第几个?后面的参数代表需要替换的值
statement.setString(2,mima);
/*
*
Statement statement = connection.createStatement();//获取sql语句执行对象,执行事物
String sql = "select u_username from yinhang where u_username="+"'usrname'"+"and"+" u_mima = "+ "'mima'";//查询语句
ResultSet set = statement.executeQuery(sql);
用此方法会产生sql注入问题,一般插入删除会比较关注注入问题,需要用 PreparedStatement方法解决
*
*/
ResultSet set = statement.executeQuery();//执行dml操作
System.out.println(set.next());
//这东西返回的结果是个集合
if (set.next()){//向下移动,从表头开始的,如果不能移动的那就一个数据都没有,能移动表名可移动,说明有重复的
System.out.println("账号以存在");
}
if(set != null && !set.isClosed()){
set.close();//关闭结果
}
if (statement != null && !statement.isClosed()){
statement.close();//关闭提交
}
if (connection != null && !connection.isClosed()){
connection.close();//关闭连接
}
}
}