一、JDBC
1. 概述
sun公司提供的一套 java操作数据库的标准
专门用来完成 java 和 数据库 交互的技术,全称是: java database connectivity
2. 使用步骤
- 提供了丰富的工具类jar包,项目中导入jar包
- 连接数据库: 端口号3306 库名cgb2109 用户名root 密码root
- 写SQL语句
- 处理数据库返回给java的结果
3. 导入jar包
-
选用哪个版本的jar包,要看你安装的数据库的版本
-
复制粘贴到工程里
-
选中jar包,右键-add as libarary
-
点击ok
4.测试
package cn.tedu.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
//测试jdbc
public class Test1 {
//junit单元测试:@Test public void 没有参数
//需求:利用java查询数据库中dept表的所有数据
@Test
public void get() throws Exception {
//1.注册驱动 —— 利用反射获取Driver,参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,并返回了数据库的连接Connection
// 遵循的协议://本机ip地址:端口号/数据库名
String url="jdbc:mysql://localhost:3306/cgb2109";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.获取传输器
Statement s = c.createStatement();
//4.执行SQL语句
//需求:利用java查询数据库中dept表的所有数据
ResultSet r = s.executeQuery("select * from dept");//执行查询的SQL语句
//s.executeUpdate(); //执行增删改的SQL语句
//5.处理结果
while (r.next()){ //next()判断有没有数据
//getXxx()获取不同类型的数据
//r.getInt(1); //根据列的编号获取列的值
int a = r.getInt("deptno"); //根据列名获取列的值
String b = r.getString("dname");
String d = r.getString(3);
System.out.println(a+b+d);
}
//6.释放资源
r.close(); //结果集
s.close(); //传输器
c.close(); //连接器
System.out.println("java和数据库连接成功!!");
}
}
二、JDBC练习
1. 查询courses表的所有数据
//需求:查询courses表的所有数据
@Test
public void get2() throws Exception {
//1.注册驱动 —— 利用反射获取Driver,参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,并返回了数据库的连接Connection
// 遵循的协议://本机ip地址:端口号/数据库名
//?characterEncoding=utf8防止中文乱码
String url="jdbc:mysql://localhost:3306/cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.获取传输器
Statement s = c.createStatement();
//4.执行SQL语句
ResultSet r = s.executeQuery("select * from courses");//执行查询的SQL语句
//s.executeUpdate(); //执行增删改的SQL语句
//5.处理结果
while (r.next()){ //next()判断有没有数据
while (r.next()){ //判断有没有数据
//表里有三列,循环三次就行了
for (int i = 1; i < 4; i++) {
//获取数据getXxx()——getObject()更通用可以获取任何类型的数据
Object a = r.getObject(i);//i是列的索引1 2 3..列
System.out.println(a); //打印每列的值
}
}
}
//6.释放资源
r.close(); //结果集
s.close(); //传输器
c.close(); //连接器
}
2. 向dept表中插入数据
//需求:向dept表中插入数据
@Test
public void get3() throws Exception {
//1.注册驱动 —— 利用反射获取Driver,参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,并返回了数据库的连接Connection
// 遵循的协议://本机ip地址:端口号/数据库名
//?characterEncoding=utf8防止中文乱码
//String url="jdbc:mysql://localhost:3306/cgb2109?characterEncoding=utf8";
String url="jdbc:mysql" +
":///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.获取传输器
Statement s = c.createStatement();
//4.执行SQL语句
int rows = s.executeUpdate("insert into dept values (null,'MySQL',\"上海\")");//执行查询的SQL语句
//s.executeUpdate(); //执行增删改的SQL语句
//5.处理结果
//查询,会把结果返回给ResultSet需要遍历
//增删改,会返回对数据库的影响行数,通常不处理
//6.释放资源
s.close(); //传输器
c.close(); //连接器
}
3.模拟用户登录
1. 让用户输入用户名和密码
2. 在数据库里准备表
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(20) default NULL,
`pwd` varchar(10) default NULL,
PRIMARY KEY (`id`)
)
3. 使用JDBC查询库,发起select语句
package cn.tedu.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
//模拟用户登录
public class Test2 {
@Test
public void login() throws Exception {
//1.注册驱动 —— 利用反射获取Driver,参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,并返回了数据库的连接Connection
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.获取传输器
Statement s = c.createStatement();
//4.执行SQL语句
String sql = "select * from user where name='jack' and pwd='123'";
ResultSet r = s.executeQuery(sql);
//5.处理结果
if (r.next()){ //判断有数据吗?如果有数据就可以登录
System.out.println("登陆成功");
} else { //没数据,需要输入或去注册
System.out.println("登录失败,请重新输入或去注册");
}
//6.释放资源
r.next(); //结果集
s.close(); //传输器
c.close(); //连接器
}
}
三、SQL攻击
1. 模拟SQL攻击的现象
package cn.tedu.jdbc;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
//模拟用户登录
public class Test2 {
//出现了问题:
//SQL攻击:
//1.本质上就是因为SQL中出现了特殊符号#,#号在SQL中是注释的意思(测试时使用固定的用户名jack’#)
//2.Statement传输器在执行SQL时遇到了SQL拼接,把#当做了注释用!!
//模拟用户登录:从单元测试改成main()原因,就是IDEA单元测试方法无法键盘输入
public static void main(String[] args) throws Exception {
//1.注册驱动 —— 利用反射获取Driver,参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,并返回了数据库的连接Connection
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.获取传输器
Statement s = c.createStatement();
//4.执行SQL语句
System.out.println("请输入用户名:");
String username = new Scanner(System.in).nextLine();
System.out.println("请输入密码:");
String password = new Scanner(System.in).nextLine();
//拼接字符串: 一对儿双引号中间一对儿加号 再中间看你了 "+???+"
//String sql = "select * from user where name='jack' and pwd='123'";
String sql = "select * from user where name='"+username+"' and pwd='"+password+"'";
ResultSet r = s.executeQuery(sql);
//5.处理结果
if (r.next()){ //判断有数据吗?如果有数据就可以登录
System.out.println("登陆成功");
} else { //没数据,需要输入或去注册
System.out.println("登录失败,请重新输入或去注册");
}
//6.释放资源
r.next(); //结果集
s.close(); //传输器
c.close(); //连接器
}
}
2. 解决方案
package cn.tedu.jdbc;
import org.junit.Test;
import java.sql.*;
import java.util.Scanner;
//模拟用户登录
public class Test2 {
//出现了问题:
//SQL攻击:
//1.本质上就是因为SQL中出现了特殊符号#,#号在SQL中是注释的意思(测试时使用固定的用户名jack’#)
//2.Statement传输器在执行SQL时遇到了SQL拼接,把#当做了注释用!!
//模拟用户登录:从单元测试改成main()原因,就是IDEA单元测试方法无法键盘输入
public static void main(String[] args) throws Exception {
//1.注册驱动 —— 利用反射获取Driver,参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2.连接数据库,并返回了数据库的连接Connection
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.获取传输器
//Statement s = c.createStatement(); //SQL攻击问题
//4.执行SQL语句
System.out.println("请输入用户名:");
String username = new Scanner(System.in).nextLine();
System.out.println("请输入密码:");
String password = new Scanner(System.in).nextLine();
//SQL骨架,?叫占位符
String sql = "select * from user where name=? and pwd=?";
//准备执行预编译的SQL
//PreparedStatement 好处:SQL简单,安全(解决SQL攻击),高效
PreparedStatement s = c.prepareStatement(sql);
//设置SQL中的参数
s.setObject(1,username); //给第一个?设置用户名
s.setObject(2,password); //给第二个?设置密码
ResultSet r = s.executeQuery();
//5.处理结果
if (r.next()){ //判断有数据吗?如果有数据就可以登录
System.out.println("登陆成功");
} else { //没数据,需要输入或去注册
System.out.println("登录失败,请重新输入或去注册");
}
//6.释放资源
r.next(); //结果集
s.close(); //传输器
c.close(); //连接器
}
}
3.练习PreparedStatement
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
//利用新的传输器,向dept表里插入数据
public class Test3 {
public static void main(String[] args) throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
//3.传输器
System.out.println("请输入部门名称:");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入地址:");
String address = new Scanner(System.in).nextLine();
String sql = "insert into dept values (null,?,?)";
PreparedStatement p = c.prepareStatement(sql);
//设置SQL中的参数——给第几个?设置啥值
p.setObject(1,name);
p.setObject(2,address);
//4.执行SQL
p.executeUpdate(); //执行增删改的SQL,返回影响行数
//5.处理结果
//6.释放资源
p.close(); //传输器
c.close(); //连接器
}
}
四、程序优化
JDBC的前两步,重复的写了很多次,优化这种现象
1.提供类
2.提供方法(封装JDBC的前两步)
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
public class JDBCUtils {
//封装了注册驱动,获取连接。
//目的:获取连接,并返回给调用者
static public Connection get () throws Exception {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
String url = "jdbc:mysql://localhost:3306/cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","123456");
return c; //返回给调用者
}
}
3.调用类里的方法
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Scanner;
//利用新的传输器,向dept表里插入数据
public class Test3 {
public static void main(String[] args) throws Exception {
Connection c = JDBCUtils.get(); //利用工具类里封装好的方法
//3.传输器
System.out.println("请输入部门名称:");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入地址:");
String address = new Scanner(System.in).nextLine();
String sql = "insert into dept values (null,?,?)";
PreparedStatement p = c.prepareStatement(sql);
//设置SQL中的参数——给第几个?设置啥值
p.setObject(1,name);
p.setObject(2,address);
//4.执行SQL
p.executeUpdate(); //执行增删改的SQL,返回影响行数
//5.处理结果
//6.释放资源
p.close(); //传输器
c.close(); //连接器
}
}