文章目录
一、回顾
1.jdbc基本使用步骤!(代码表示)
1.定义静态数据库链接信息
2.加载驱动(mysql)
3.创建链接对象
4.创建执行sql的对象
书写sql
执行
5.处理结果(结果集)
int
reslutset
6.释放资源
2.写出jdbc设计的核心类和接口、并简单描述作用!
1.driver
2.connection
3.statement
4.resulteset
3.实现一个控制台登陆方式:
- 创建一张用户表 User
- id ,主键、自动增长。
- 用户名,字符串类型,唯一、非空
- 密码,字符串类型,非空
- 手机号码,字符串类型
- 插入 2 条测试语句
CREATE TABLE `users` (
`userId` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(11) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`phone` varchar(255) DEFAULT NULL,
PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
实现过程:
- 通过控制台用户输入用户名和密码。
--实质:通过控制台接收两个变量 username password
- 用户输入的用户名和密码作为条件,编写查询 SQL 语句。
登陆的实质就是查询
sql:select * from users where username=XXX and password=XXX;
- 如果该用户存在,提示登录成功,反之提示失败。
判断验证
1.1用户登陆的实现方式一
// 实例化控制台输入
Scanner scanner = new Scanner(System.in);
System.out.println("输入用户名");
// 注意:控制台接收的所有数据全部是字符串类型
String username = scanner.nextLine();
System.out.println("输入密码");
String password = scanner.nextLine();
// 开始链接数据库
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.创建链接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb","root","root");
// 3.创建执行sql的对象
Statement statement = connection.createStatement();
String sql = "select * from users where username='"+username+"' and password='"+password+"';";
ResultSet resultSet = statement.executeQuery(sql);
// 4.处理结果集
if (resultSet.next()){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
// 5.释放资源
resultSet.close();
statement.close();
connection.close();
' or 1='1
1.2什么是sql注入
用户输入的数据中存在sql的关键字或者语法并且参与了sql语句的编译,导致sql语句编译之后条件的含义一直为true,不能得到正确的结果,这就是sql注入。
1.3如何避免sql注入
预编译
由于编写的sql语句是再用户输入数据,整合之后再进行的编译,所以为了避免sql的注入,我们需要将sql语句再用户整合执行之前进行sql编译,然后再填充数据。
1.4prepareStatement【重点】
prepareStatement接口继承了Statement,执行sql方式没有任何编译区别。
1.5prepareStatement的应用
作用:
1.可与预编译sql,效率高
2.安全,避免sql注入
3.可以动态的填充数据。执行多个同构的sql语句
二、prepareStatement的预编译应用
2.1解决登陆注入问题
String sql = "select * from users where username=? and password=?;";
// 预编译
PreparedStatement pstm = connection.prepareStatement(sql);
// 参数1和参数2的类型
// statement.setInt();
// statmen.setString();
// 类似与添加变量
pstm.setObject(1,username);
pstm.setObject(2,password);
// 编译执行之后接收结果
ResultSet resultSet = pstm.executeQuery();
// statement.setString(1,username);
// object和String为什么都不报错
// string 根据我们设定的变量去分析使用哪些类型
占位符?的处理和赋值
/*
* 预编译sql:使用?代替参数值 一个问号代表一个
* ? 占位
* 解决问号:
* 设置参数
* 参数1 --->用户名
* 参数2 ---->密码
*
* 根据参数为设置数字,从1开始
* 参数的实际值
*/
总结:解决sql注入,我们可以选择预编译方式,仔细查看代码的执行顺序,我们会发现再结果出现之前我们已经执行了sql的编译,通过占位符?去处理编译的数据,可选择的类型建议使用object,最后对产生的结果集进行判断,实现登陆和登陆失败,并解决注入问题。
2.2完整实现登陆的注入解决代码
// 实例化控制台输入
Scanner scanner = new Scanner(System.in);
System.out.println("输入用户名");
// 注意:控制台接收的所有数据全部是字符串类型
String username = scanner.nextLine();
System.out.println("输入密码");
String password = scanner.nextLine();
// 开始链接数据库
// 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2.创建链接对象
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb","root","root");
// 3.创建执行sql的对象
String sql = "select * from users where username=? and password=?;";
// 预编译
PreparedStatement pstm = connection.prepareStatement(sql);
// 参数1和参数2的类型
// statement.setInt();
// statmen.setString();
// 类似与添加变量
pstm.setObject(1,username);
pstm.setObject(2,password);
// 编译执行之后接收结果
ResultSet resultSet = pstm.executeQuery();
// statement.setString(1,username);
// object和String为什么都不报错
// string 根据我们设定的变量去分析使用哪些类型
/*
* 预编译sql:使用?代替参数值 一个问号代表一个
* ? 占位
* 解决问号:
* 设置参数
* 参数1 --->用户名
* 参数2 ---->密码
*
* 根据参数为设置数字,从1开始
* 参数的实际值
*
/
*/
// 4.处理结果集
if (resultSet.next()){
System.out.println("登陆成功");
}else{
System.out.println("登陆失败");
}
// 5.释放资源
resultSet.close();
pstm.close();
connection.close();
2.3使用preparement实现DDL和DML操作
@Test
public void test1(){
// 初始化对象的
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(URL,USER,PASSWORD);
// 创建执行sql的对象
String sql = "insert into stu(id,name,sex) values(?,?,?);";
preparedStatement= connection.prepareStatement(sql);
// 处理?
preparedStatement.setObject(1,5);
preparedStatement.setObject(2,"打老虎");
preparedStatement.setObject(3,"没打着");
int count = preparedStatement.executeUpdate();
System.out.println("你的打老虎影响了"+count+"行");
} catch (Exception e) {
e.printStackTrace();
}finally {
// 6.释放资源 判断当前链接是否还继续存在
if (preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 释放连接
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
三、JDBC的封装
刚开始接触的,全部是用原生
3.1类型的介绍(重点)
类类型
封装的工具类的类型
实体类(实体的对象是数据库中的表):承接数据,数据库中数据的一种体现,踏踏实实的按照数据库的格式和类型声明这个类
属性:对应数据表中列名
行为:get/set
持久化类
增、删、改、查
格式:XXX实体类
工具类:工具类可以帮助逻辑类形成一些简化的操作
XXX工具类
3.2工具类的编程思想
工具类本身没有任何的逻辑可言,就是为了简化其他的逻辑类,提供一些方法
学会自己封装工具类
3.3重用性(可以重复使用)
1.创建一个类(工具类)
2.进行JDBC部分重复使用的方法和代码
3.封装注册的驱动
4.封转简化的创建链接方式
5.封转释放资源的方法(可以进行方法重载)
6.封装简化的sql的语句
JDBC的封装工具类
public class DBunti {
private static String URL = "jdbc:mysql://127.0.0.1:3306/companydb"; //数据库链接的url
private static String USER = "root"; //数据库的用户名
private static String PASSWORD = "root"; //数据库的密码
// 加载驱动
static { //类加载 只加载一次
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
//1.获取连接
public static Connection getConnection(){
Connection connection = null;
try {
connection = DriverManager.getConnection(URL,USER,PASSWORD);
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
// 2.释放资源
public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
if (resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.4工具类的使用
// 删除
@Test
public void test1() throws SQLException {
// 注册驱动
Connection connection = null;
PreparedStatement preparedStatement = null;
int id =6;
connection = DBunti.getConnection();
// 表名 字段名 must不能使用关键字
String sql = "delete from stu where id=?;";
preparedStatement = connection.prepareStatement(sql);
// 参数处理
preparedStatement.setObject(1,id);
int count = preparedStatement.executeUpdate();
System.out.println("你的操作影响了"+count+"行");
DBunti.close(connection);
}
@Test
public void test2() throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
String name1 = "王%";
// 注册驱动
connection = DBunti.getConnection();
// 表名 字段名 must不能使用关键字
String sql = "select * from stu where name like ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1,name1);
ResultSet resultSet = preparedStatement.executeQuery();
// 迭代
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
String sex = resultSet.getString("sex");
System.out.println(id+"\t"+name+"\t"+sex+"\t");
}
DBunti.close(connection);
}
总结:面试题:statement和preparement的区别
一、语法结构
1.只可以执行静态的sql,并且sql可以进行拼接(“++”)
2.preparement可以限制性预编译的sql,在执行sql语句中使用?进行占位,再进行占位符的处理(再赋值)
二、原理
1.preparement执行效率比statement快
2.statement不能进行sql缓存
三、安全性的不同
1.statement不能有效的防止sql注入
2.preparement可以防止sql注入
四、实际应用中,哪些地方使用preparement。。。
3.5跨平台性
XXX.properties
Properties(Java.util.Properties),该类主要用于读取Java的配置文件,不同的编程语言有自己所支持的配置文件,配置文件中很多变量是经常改变的,为了方便用户的配置,能让用户够脱离程序本身去修改相关的变量设置。就像在Java中,其配置文件常为.properties文件,是以键值对的形式进行参数配置的。
Properties这个类里面
public static final Properties pro = new Properties() //配置文件的集合(map)
IDEA创建properties文件如何创建?
创建模板
file--->settings---->Editor---->file and code templates --->点击加号--->设置文件名字以及文件后缀名(Properties)---->点击enable live templates---->ok
将模板进行保留,一边后续使用。
跨平台完整封装
public class DButils {
// 实例化
private static final Properties PROPERTIES = new Properties();
static {
// 通过流的作用将这个文件进行使用
InputStream is = DButils.class.getResourceAsStream("/db.properties");
try {
PROPERTIES.load(is);
Class.forName(PROPERTIES.getProperty("driver"));
// 如果报一下异常 说明我们文件输入出现问题
} catch (IOException e) {
e.printStackTrace();
// 说明文件中的属性出现异常
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection connection = null;
try {
connection = DriverManager.getConnection(PROPERTIES.getProperty("url"),PROPERTIES.getProperty("user"),PROPERTIES.getProperty("password"));
} catch (SQLException e) {
e.printStackTrace();
}
return connection;
}
// 2.释放资源
public static void close(Connection connection){
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}