jdbc(2)
1.sql注入安全问题
public static void main(String[] args) throws Exception {
Scanner sc=new Scanner(System.in);
System.out.print("请输入账号:");
String name=sc.nextLine();
System.out.print("请输入密码:");
String pwd=sc.nextLine();
boolean flag = login(name, pwd);
if(flag==true){
System.out.println("登录成功,跳转主页面");
}else{
System.out.println("账号或密码错误.");
}
}
//登录方法。
private static boolean login(String name,String pwd) throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/qy174";
String user="root";
String password="root";
Connection conn= DriverManager.getConnection(url,user,password);
Statement st=conn.createStatement();
String sql="select * from tbl_user where username='"+name+"' and password='"+pwd+"'";
System.out.println(sql);
ResultSet rs=st.executeQuery(sql);
while (rs.next()){
return true; //方法遇到return 方法结束。
}
return false;
}

处理sql注入安全隐患问题。Statement这个类导致出现了bug. 创建了一个新的接口,该接口继承Stetement接口,并加入了自己新的功能。子接口就是PrepareStatement. s该类可以解决sql注入安全问题。
public static void main(String[] args) throws Exception {
Scanner sc=new Scanner(System.in);
System.out.print("请输入账号:");
String name=sc.nextLine();
System.out.print("请输入密码:");
String pwd=sc.nextLine();
boolean flag = login2(name, pwd);
if(flag==true){
System.out.println("登录成功,跳转主页面");
}else{
System.out.println("账号或密码错误.");
}
}
//我们以后执行sql时,都使用PreparedStatement.
private static boolean login2(String name,String pwd) throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/qy174";
String user="root";
String password="root";
Connection conn= DriverManager.getConnection(url,user,password);
//占位符:
String sql="select * from tbl_user where username=? and password=?";
PreparedStatement ps=conn.prepareStatement(sql); //预编译
//为占位符赋值
ps.setString(1,name); //1.表示第几个占位符. name表示占位符的值
ps.setString(2,pwd);
//不用在写sql.
ResultSet rs=ps.executeQuery();
while (rs.next()){
return true; //方法遇到return 方法结束。
}
return false;
}
原因:因为sql的字符串拼接导致sql注入安全问题。 为使用占位符并为占位符赋值的方式可以解决sql注入问题。
2.异常处理
private static boolean login2(String name, String pwd) {
ResultSet rs = null;
PreparedStatement ps = null;
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//占位符:
String sql = "select * from tbl_user where username=? and password=?";
ps = conn.prepareStatement(sql); //预编译
//为占位符赋值
ps.setString(1, name); //1.表示第几个占位符. name表示占位符的值
ps.setString(2, pwd);
//不用在写sql.
rs = ps.executeQuery();
while (rs.next()) {
return true; //方法遇到return 方法结束。
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
//资源关闭代码 --关闭时的顺序. 后用先关。
try {
if (rs != null) {
rs.close();//关闭资源
}
if(ps!=null){
ps.close();
}
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
return false;
}
3. 企业开发模式
把对表的操作封装到dao类中
dao层: data access object(数据访问对象层) 以后我们对表的操作习惯放在dao包下。每张表对应一个dao类。而该类中包含所有数据该表的操作【crud】。
比如: tbl_user表---->UserDao类该类中包含了对该tbl_user表操作的各种方法。 tbl_teacher---->TeacherDao类。
package com.ykq.dao;
import java.sql.*;
public class UserDao { //类的命名: 首字母必须大写。而且按照驼峰命名[每个单词的首字符必须大写]。
//方法名命名: 第一个单词的首字母小写。
public void selectById(int id){
PreparedStatement ps = null;
Connection conn = null;
try {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//3. 获取执行sql语句的对象。PreparedStatement
String sql = "select * from tbl_user where id=?";
ps = conn.prepareStatement(sql);
//4. 为占位符赋值
ps.setInt(1, id);
//5.执行sql.
ResultSet rs = ps.executeQuery();
//6.遍历
while (rs.next()){
int id1 = rs.getInt("id");
String username = rs.getString("username");
String password1 = rs.getString("password");
String realname = rs.getString("realname");
System.out.println("编号:"+id+";账号:"+username+";密码:"+password1+";真实姓名:"+realname);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 修改
* @param id
* @param name
* @param pwd
* @param realname
* @return
*/
public int updateById(int id,String name,String pwd,String realname){
PreparedStatement ps = null;
Connection conn = null;
try {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//3. 获取执行sql语句的对象。PreparedStatement
String sql = "update tbl_user set username=?,password=?,realname=? where id=?";
ps = conn.prepareStatement(sql);
//4. 为占位符赋值
ps.setString(1,name);
ps.setString(2,pwd);
ps.setString(3,realname);
ps.setInt(4, id);
//5.执行sql.
int i = ps.executeUpdate();
return i;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 根据id删除
* @param id 主键值
* @return 影响的行数
*/
public int deleteById(int id){
PreparedStatement ps = null;
Connection conn = null;
try {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//3. 获取执行sql语句的对象。PreparedStatement
String sql = "delete from tbl_user where id=?";
ps = conn.prepareStatement(sql);
//4. 为占位符赋值
ps.setInt(1, id);
//5.执行sql.
int i = ps.executeUpdate();
return i;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 添加用户的功能
*
* @param name 账号
* @param pwd 密码
* @param realname 真实姓名
* @return 影响的条数
*/
public int insertUser(String name, String pwd, String realname) {
PreparedStatement ps = null;
Connection conn = null;
try {
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//3. 获取执行sql语句的对象。PreparedStatement
String sql = "insert into tbl_user values(null,?,?,?)";
ps = conn.prepareStatement(sql);
//4. 为占位符赋值
ps.setString(1, name);
ps.setString(2, pwd);
ps.setString(3, realname);
//5.执行sql.
int i = ps.executeUpdate();
return i;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
try {
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
}
把表中的数据封装到entity类中。
我们以后把查询的记录结果封装到我们的实体类中。为了在网页中展示。 我们上面写的查询操作,都是在控制台打印的。
我们就应该把查询的结果封装到java类对象中,调用者就可以获取该java类对象。展示对应的数据了。 我们习惯把数据
库中表记录封装到对应的实体类中。 比如: tbl_user---->User实体类。
//查询用户表中所有的记录.
public List<User> selectAll() throws Exception{
Connection conn=null;
PreparedStatement ps=null;
//创建集合容器
List<User> list = new ArrayList<>();
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//3.获取执行sql语句的对象。PreparedStatement
String sql = "select * from tbl_user";
ps = conn.prepareStatement(sql);
//4.执行sql
ResultSet rs=ps.executeQuery();
while (rs.next()){
User user1=new User();//创建实体类对象
user1.setId(rs.getInt("id"));
user1.setUsername(rs.getString("username"));
user1.setPassword(rs.getString("password"));
user1.setRealname(rs.getString("realname"));
list.add(user1);//把java实体类对象放入集合中
}
return list;
}
//方法名命名: 第一个单词的首字母小写。
public User selectById(int id) throws Exception {
PreparedStatement ps = null;
Connection conn = null;
User u = null;//声明一个User类的实体类
//1. 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/qy174";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
//3. 获取执行sql语句的对象。PreparedStatement
String sql = "select * from tbl_user where id=?";
ps = conn.prepareStatement(sql);
//4. 为占位符赋值
ps.setInt(1, id);
//5.执行sql.
ResultSet rs = ps.executeQuery();
//6.遍历
while (rs.next()) {
u = new User(); //实例化类对象
//查询当前记录中对应列的值
int id1 = rs.getInt("id");
String username = rs.getString("username");
String password1 = rs.getString("password");
String realname = rs.getString("realname");
//为实体类的属性赋值
u.setId(id1);
u.setUsername(username);
u.setPassword(password1);
u.setRealname(realname);
}
return u;
}
总结: 1. 查询的表--封装了实体类---- 字段名---实体类的属性名 表中一条记录---对应实体类的一个对象中。
浙公网安备 33010602011771号