目录
一,JDBC
–1,概念
–2,使用步骤
–3,导入jar包
二,Java与数据库的连接操作
1.获取数据库数据(查询表数据)
2.写入数据库数据(向表中插入数据)
–5,模拟用户登录
三,SQL攻击
–1,模拟SQL攻击的现象
–2,SQL攻击解决方案
–1,模拟SQL攻击的现象
–2,解决方案
–3,练习PreparedStatement
四,扩展: 程序优化
1,创建工具类
2,改造测试类
3,小结
我们学习了数据库,数据库实现了数据的持久化,但我们最终要在程序里处理数据啊,那java代码中怎么去访问数据库读写数据呢?
这就要用到sun公司设定的一套数据库标准了,这套标准就是JDBC(Java Database Connectivity)。但它只是规范,不做具体实现。于是数据库厂商又根据JDBC标准,实现自家的驱动Driver。如:mysql驱动com.mysql.cj.jdbc.Driver,Oracle的驱动oracle.jdbc.OracleDriver。有了这套解决方案,java就可以访问数据库中的数据了。
public interface Connection extends Wrapper, AutoCloseable {}
public interface Statement extends Wrapper, AutoCloseable {}
public interface PreparedStatement extends Statement {}
public interface CallableStatement extends PreparedStatement {}
public interface ResultSet extends Wrapper, AutoCloseable {}
Java中提倡面向接口开发,而最经典的接口设计莫过于JDBC数据库接口。
Connection链接、Statement语句、PreparedStatement预处理语句、CallableStatement存储过程、ResultSet结果集。
调用方式有三种:Statement语句、PreparedStatement预处理语句、CallableStatement存储过程,推荐使用第二种PreparedStatement,防止SQL注入,其也是预编译性能高。
1, 提供了丰富的工具类jar包,项目中导入jar包
2, 连接数据库: 端口号3306 库名cgb2109 用户名root 密码root
3, 写SQL
4, 处理数据库返回给java的结果
1, 复制粘贴到工程里
2, 选中jar包,右键-add as libarary… ok
连接数据库
1.加载JDBC驱动:
Class.forName("com.mysql.cj.jdbc.Driver");
2.连接数据库,传入连接地址,用户名,密码:
String address = "jdbc:maysql://连接地址:3306/数据库据名characterEncoding = utf8&serverTimezone = Asia/Shanghai&useSSL=false";
String dataBaseName = "用户名";
String dataBasePwd = "密码";
Connection com = DriverManager.getConnection(address,dataBaseNam,dataBasePwd )
中文乱码
url增加参数:characterEncoding=utf8防止中文乱码
String url ="jdbc:mysql://localhost:3306/mydb?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
获取数据库测试
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 没有参数
@Test
public void get() throws Exception {
//1,注册驱动 --参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");//5版本的jar包
//Class.forName("com.mysql.cj.jdbc.Driver");//8版本的jar包
//2,连接数据库,并返回了数据库的连接Connection
String url = "jdbc:mysql://localhost:3306/cgb2109";
//遵循的协议://本机ip地址:端口号/数据库名
Connection c = DriverManager.getConnection(url,"root","root");
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL语句
//需求:利用java查询数据库中dpet表的所有数据
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();//连接器
}
}
小结
获取数据库数据测试优化
package cn.tedu.jdbc;
import org.junit.Test;
import java.sql.*;
//测试jdbc
public class Test1 {
//junit单元测试:@Test public void 没有参数
//需求:查询courses表的所有数据
@Test
public void get2() throws Exception{
//1,注册驱动 --参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2,连接数据库,并返回了数据库的连接Connection
String url="jdbc:mysql://localhost:3306/cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url,"root","root");
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL
ResultSet r = s.executeQuery("select * from courses");//查询SQL
//5,处理结果
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();
}
//需求:利用java查询数据库中dpet表的所有数据
@Test
public void get() throws Exception {
//1,注册驱动 --参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");//5版本的jar包
//Class.forName("com.mysql.cj.jdbc.Driver");//8版本的jar包
//2,连接数据库,并返回了数据库的连接Connection
String url = "jdbc:mysql://localhost:3306/cgb2109";
//遵循的协议://本机ip地址:端口号/数据库名
Connection c = DriverManager.getConnection(url,"root","root");
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL语句
//需求:利用java查询数据库中dpet表的所有数据
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和数据库连接成功!!");
}
}
//需求:向dept表中插入数据
@Test
public void add() throws Exception{
//1,注册驱动 --参数是类的全路径
Class.forName("com.mysql.jdbc.Driver");
//2,连接数据库,并返回了数据库的连接Connection
// String url="jdbc:mysql://localhost:3306/cgb2109?characterEncoding=utf8";
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";//简写
Connection c = DriverManager.getConnection(url,"root","root");
//3,获取传输器
Statement s = c.createStatement();
//4,执行SQL
int rows = s.executeUpdate(
"insert into dept values(null,'java开发',\"北京\")");
//5,处理结果
//executeQuery查询,会把结果返回给ResultSet需要遍历,,,
//executeUpdate增删改,会返回对数据库的影响行数,,,通常不处理
//6,释放资源
s.close();
c.close();
}
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语句
select * from user where name=‘jack’ and password=‘123’
package cn.tedu.jdbc;
import org.junit.Test;
import java.awt.*;
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,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2,连接数据库
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url, "root", "root");
//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.close();
s.close();
c.close();
}
}
//出现了问题:SQL攻击:
//1,本质上就是因为SQL中出现了特殊符号#,#号在SQL中是注释的意思(测试时使用固定的用户名jack’#)
//2,Statement传输器在执行SQL时遇到了SQL拼接,把#当做了注释用!!
package cn.tedu.jdbc;
import org.junit.Test;
import java.awt.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
//模拟用户登录
public class Test2 {
//模拟用户登录,从单元测试改成main()原因是IDEA单元测试方法无法键盘输入
public static void main(String[] args) throws Exception{
//1,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2,连接数据库
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url, "root", "root");
//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.close();
s.close();
c.close();
}
}
//出现了问题:SQL攻击:
//1,本质上就是因为SQL中出现了特殊符号#,#号在SQL中是注释的意思(测试时使用固定的用户名jack’#)
//2,Statement传输器在执行SQL时遇到了SQL拼接,把#当做了注释用!!
package cn.tedu.jdbc;
import org.junit.Test;
import java.awt.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
//模拟用户登录
public class Test2 {
//模拟用户登录,从单元测试改成main()原因是IDEA单元测试方法无法键盘输入
public static void main(String[] args) throws Exception{
//1,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2,连接数据库
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url, "root", "root");
//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.close();
s.close();
c.close();
}
}
package cn.tedu.jdbc;
import org.junit.Test;
import java.awt.*;
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,注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2,连接数据库
String url="jdbc:mysql:///cgb2109?characterEncoding=utf8";
Connection c = DriverManager.getConnection(url, "root", "root");
//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();
// String sql="select * from user where name='"+username+"' and pwd='"+password+"'";
//SQL骨架,?叫占位符
String sql="select * from user where name=? and pwd=?";
//准备执行预编译的SQL
//PreparedStatement好处:SQL简单,安全(解决SQL攻击),高效
PreparedStatement s = c.prepareStatement(sql);
//设置SQL中的参数
s.setObject(1,username);//给第1个?设置用户名
s.setObject(2,password);//给第2个?设置用户名
ResultSet r = s.executeQuery();
//5,处理结果
if( r.next() ){//判断有数据吗?如果有数据就可以登录
System.out.println("登录成功!");
}else{//没数据,重新输入或去注册
System.out.println("登录失败,请重新输入或去注册!");
}
//6,释放资源
r.close();
s.close();
c.close();
}
}
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
//需求:利用新的传输器,向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", "root");
//3,传输器
String sql ="insert into dept values(null,?,?)";//SQL骨架
PreparedStatement p = c.prepareStatement(sql);
//设置SQL中的参数--给第几个?设置啥值
p.setObject(1,"php开发部");
p.setObject(2,"北京");
//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", "root");
return c; //返回给调用者
}
}
3,调用类里的方法
package cn.tedu.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
//需求:利用新的传输器,向dept表里插入数据
public class Test3 {
public static void main(String[] args) throws Exception{
//TODO 利用工具类里封装好的方法
Connection c = JDBCUtils.get();
//3,传输器
String sql ="insert into dept values(null,?,?)";//SQL骨架
PreparedStatement p = c.prepareStatement(sql);
//设置SQL中的参数--给第几个?设置啥值
p.setObject(1,"php开发部");
p.setObject(2,"北京");
//4,执行SQL
p.executeUpdate();//执行增删改的SQL,返回影响行数
//5,处理结果
//6,释放资源
c.close();
p.close();
}
}
mysql数据库知识已经基本学习完成了,希望每一个小伙伴都能实现自己的梦想。
加油~~~~