DAY09
Demo01_jdbc入门案例
package com.ujiuye.demo;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 1、导入jar包
* 2、加载驱动
* 3、获取连接
* 4、创建sql执行器和编写sql
* 5、执行sql返回结果集
* 6、释放资源
*
* 涉及的API(java.sql.* 或 javax.sql.*)
* 1. DriverManager类 管理不同的驱动
* 2. Connection 接口 应用和数据库的连接
* 3. Statement 接口 用于执行sql语句
* 4. ResultSet 接口 保存查询的结果
*/
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接
String url = "jdbc:mysql:///day07?serverTimezone=UTC";
String name = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url,name,password);
// 测试连接
System.out.println(conn);
// 创建sql执行器和编写sql
String sql = "insert into users values(20,'王小二',20000)";
Statement stat = conn.createStatement();
// 运行执行器执行sql语句
// 执行sql返回结果集
// executeUpdate()方法返回受影响的行数
// executeQuery() 返回resultSet结果集
int i = stat.executeUpdate(sql);
if (i > 0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
// 释放资源
conn.close();
stat.close();
}
}
Demo02_jdbc查询
package com.ujiuye.demo;
import sun.applet.Main;
import java.sql.*;
public class Demo02_jdbc查询 {
public static void main(String[] args) throws Exception {
// 加载驱动
//如果是jdbc5.0版本 com.mysql.jdbc.Driver
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接
//如果地址是localhost 端口号是默认的3306 使用下面简写的方式(将localhost:3306省略掉)
String url = "jdbc:mysql:///day07?serverTimezone=UTC";
String user = "root";
String password = "root";
Connection conn = DriverManager.getConnection(url,user,password);
// 测试连接 输出地址为连接成功
System.out.println("conn=" + conn);
// 创建sql查询语句
String sql = "select * from users";
// 创建sql执行器
Statement stat = conn.createStatement();
// 执行执行器,返回结果集
ResultSet rs = stat.executeQuery(sql);
// 查询结果集 使用next()
/**
* rs.next() 判断是否有下一条数据 有true 没有 false
* rs.getXXX(index/"字段名") rs.getString() rs.getInt()
* 通过index或者字段名获取对应的数据
*/
while(rs.next()) {
System.out.println(rs.getInt(1) +" "
+ rs.getString("uname")+ " " +
rs.getDouble(3));
}
conn.close();
stat.close();
rs.close();
}
}
jdbc连接方法和关闭资源方法的封装
MyUtils工具类
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
/**
*
* 做jdbc的操作,每次都要写加载驱动、获取连接、释放资源,代码重复
* 封装jdbc工具类
* 工具类
* 属性和行为 都是静态 构造私有法
* 要封装的方法
* 1、获取连接 封装成一个静态方法 getConnection()
* 2、释放资源 封装成一个静态方法 close()
*/
public class MyUtils {
private static Connection conn;
private MyUtils(){}
//在静态代码块中加载好连接对象
static {
Properties p = new Properties();
try {
// 读取配置文件
p.load(new FileInputStream(("config.properties")));
// 通过key值获取value值
String className = p.getProperty("className");
String url = p.getProperty("url");
String user = p.getProperty("user");
String password = p.getProperty("password");
// 加载驱动
Class.forName(className);
// 获取连接
conn = DriverManager.getConnection(url,user,password);
} catch (Exception e) {
e.printStackTrace();
}
} // 获取连接方法
public static Connection getConnection(){
return conn;
}
// 释放资源方法
public static void close(Connection conn, Statement stat, ResultSet rs){
try {
if(conn != null) {
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(stat != null) {
stat.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(rs != null) {
rs.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
配置文件config.properties
className=com.mysql.cj.jdbc.Driver
user=root
password=root
url=jdbc:mysql:///day07?serverTimezone=UTC
测试工具类
package com.ujiuye.demo;
import com.ujiuye.utils.MyUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo03_测试jdbc工具类 {
public static void main(String[] args) throws SQLException {
Connection conn = MyUtils.getConnection();
System.out.println("conn" + conn);
String sql = "select * from users";
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
while(rs.next()) {
System.out.println(rs.getString("uname"));
}
MyUtils.close(conn,stat,null);
}
}
sql注入原理
package com.ujiuye.demo;
import com.ujiuye.utils.MyUtils;
import java.sql.*;
import java.util.Scanner;
/**
* CREATE TABLE user1(
* uid INT PRIMARY KEY,
* username VARCHAR(20),
* `password` VARCHAR(20)
* )
* 模拟登陆
*/
public class Demo04_sql注入 {
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
System.out.println("欢迎登录:");
System.out.println("请输入账号:");
String username = scanner.nextLine();
System.out.println("请输入密码:");
String password = scanner.nextLine();
// 获取连接
Connection conn = MyUtils.getConnection();
String sql = "select * from user1 where uname = '"+ username +"' and password = '"+ password +"'";
System.out.println(sql);
// 创建sql执行器
Statement stat = conn.createStatement();
// 执行sql
ResultSet rs = stat.executeQuery(sql);
// 密码如果为888' or '1' = '1
//1=1是恒成立的,无论账号和密码输入的是多少 都能查询到数据
System.out.println(rs.next() ? "登录成功" : "登录失败");
MyUtils.close(conn,stat,rs);
}
}
防止sql注入
package com.ujiuye.demo;
import com.ujiuye.utils.MyUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner;
/**
* 原因: sql可以识别关键字
* statement 这个sql执行器不安全 可以识别sql关键字
* preparedstatement sql执行器
* 是statement的一个子接口,对参数使用占位符?进行占位,提前对sql进行预编译,
* 在对占位符进行赋值,不能识别关键字的 极大程度上防止sql注入
*/
public class Demo05_防止sql注入 {
public static void main(String[] args) throws SQLException {
Scanner scanner = new Scanner(System.in);
System.out.println("欢迎登陆:");
System.out.println("请输入账号:");
String username = scanner.nextLine();
System.out.println("请输入密码:");
String password = scanner.nextLine();
Connection conn = MyUtils.getConnection();
String sql = "select * from user1 where uname = ? and password = ?";
// 创建sql执行器
PreparedStatement ps = conn.prepareStatement(sql);
// 对占位符进行赋值
ps.setString(1,username);
ps.setString(2,password);
ResultSet rs = ps.executeQuery();
System.out.println(rs.next()?"成功":"失败");
MyUtils.close(conn,ps,rs);
}
}
Junit单元测试
package com.ujiuye.demo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/*
一个类中只有一个入口main方法,只能创建一个main方法,
有了单元测试之后,一个类中可以创建多个测试方法,测试方法可以单独运行,
简单理解为:在一个类中可以创建多个main方法
@Before 在测试方法运行之前运行
@Test 测试方法
@After 在测试方法运行之后允许
*/
public class Demo06_单元测试 {
@Test
public void test01() {
System.out.println("我是test01方法");
}
@Test
public void test02() {
System.out.println("我是test02方法");
}
@Before
public void be() {
System.out.println("我是before");
}
@After
public void after() {
System.out.println("我是after方法");
}
}