一、查找数据库

1.写入到普通的Java文件中

  1. 放jar包:将MySQL驱动jar包放到WebContent->WEB-INF->lib
    放入对应的驱动:
    • MySQL版本为5.几的可以使用mysql-connector-java-5.1.5.jar
    • MySQL版本为8.几的可以使用mysql-connector-j-8.1.0.jar
  2. 加载驱动:固定写法,会报错,原因有二:
    • 忘记放入响应的jar包
    • 异常,有两种处理方式
      • throws ClassNotFoundException:异常抛出,抛给它的调用者->main方法,main方法还不做处理,继续向上抛出
      • try{}catch(){e.printStackTrace();}:自己捕获,执行try中的操作,如果出错,catch会捕获没有找到的异常
  3. 驱动管理类调方法进行连接
    • 接受参数url、user、password,数据库不一定存在,会报异常,也进行捕获
    • 返回一个连接类接口Connection,由于DriverManager是父类,Connection是子类,需要强制转换
  4. 连接对象调用方法 创建执行sql的对象:返回Statement,由于Connection是父类,Statement是子类,需要强制转换
  5. 执行sql的对象调用方法 执行sql语句:返回ResultSet结果集
  6. 处理结果:获取返回结果中的所有字段;可以用字符串拼接,将返回的数据分装为json格式,装到数组中
    • 注意:json格式可以使用json解析工具,将想要的字段写好,直接复制过来即可,这样不易出错
  7. 关闭资源:倒着关闭,后开辟的先关闭;做判断,如果不为空,就让这个对象关闭
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class JavaMysql {
	public static void main(String[] args) {
		String sql = "select * from student";
		String aa= search(sql);
		System.out.println(aa);
	}
	//查找
	public static String search(String sql) {
		//加载驱动
		try {
			Class.forName("com.mysql.jdbc.Driver");//固定写法
			//com.mysql.jdbc.Driver:mysql版本5.几的写法
			//com.mysql.cj.jdbc.Driver:mysql版本8.几的写法
			
			String url="jdbc:mysql://localhost:3306/mysqltest";//数据库名修改为自己创建的
			String user = "root";
			String password = "root";
			
			//驱动管理类调用方法进行连接 得到连接对象  需要强制类型转换
			Connection connection = (Connection)DriverManager.getConnection(url, user, password);
			
			//连接对象调用方法 创建执行sql的对象
			Statement statement = (Statement) connection.createStatement();
			
			//执行sql的对象调用方法 执行sql语句 executeQuery查找 返回查找的结果
			ResultSet resultSet =  statement.executeQuery(sql);
			//处理结果
			String res = "[";
			while (resultSet.next()) {
				int id = resultSet.getInt("id");
				String name = resultSet.getString("name");
				String sex = resultSet.getString("sex");
				int age = resultSet.getInt("age");
				int classid = resultSet.getInt("classid");
				System.out.println(id+" "+name+" "+sex+" "+age+" "+classid);
				res+="{\"id\":"+id+",\"name\":\""+name+"\",\"sex\":\""+sex+"\",\"age\":"+age+",\"classid\":"+classid+"},";	
			}
			res = res.substring(0,res.length()-1);//去掉末尾的逗号
			res+="]";
			//关闭资源
			if(resultSet!=null) {
				resultSet.close();
			}
			if(statement!=null) {
				statement.close();
			}
			if(connection!=null) {
				connection.close();
			}
			return res;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "";
		}
	}

2. 写入到servlet文件中

  1. 写入到doGet中类中
  2. sql会报错,是因为在main方法中中传的参数,所有要加一个sql变量
  3. 返回return会报错,是因为在servlet中,返回数据使用的是response,使用getWriter().write()写入返回的数据
  4. 变量res写在了try中,所有将其写入到外面
  5. setContentType()设置返回的数据为json格式,并设置编码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	String sql = "select * from student";
	String res = "";
	//加载驱动
	try {
		Class.forName("com.mysql.jdbc.Driver");//固定写法
		//com.mysql.jdbc.Driver:mysql版本5.几的写法
		//com.mysql.cj.jdbc.Driver:mysql版本8.几的写法
		
		String url="jdbc:mysql://localhost:3306/mysqltest";
		String user = "root";
		String password = "root";
		
		//驱动管理类调用方法进行连接 得到连接对象  需要强制类型转换
		Connection connection = (Connection)DriverManager.getConnection(url, user, password);
		
		//连接对象调用方法 创建执行sql的对象
		Statement statement = (Statement) connection.createStatement();
		
		//执行sql的对象调用方法 执行sql语句 executeQuery查找 返回查找的结果
		ResultSet resultSet =  statement.executeQuery(sql);
		//处理结果
		res = "[";
		while (resultSet.next()) {
			int id = resultSet.getInt("id");
			String name = resultSet.getString("name");
			String sex = resultSet.getString("sex");
			int age = resultSet.getInt("age");
			int classid = resultSet.getInt("classid");
			System.out.println(id+" "+name+" "+sex+" "+age+" "+classid);
			res+="{\"id\":"+id+",\"name\":\""+name+"\",\"sex\":\""+sex+"\",\"age\":"+age+",\"classid\":"+classid+"},";	
		}
		res = res.substring(0,res.length()-1);//去掉末尾的逗号
		res+="]";
		//关闭资源
		if(resultSet!=null) {
			resultSet.close();
		}
		if(statement!=null) {
			statement.close();
		}
		if(connection!=null) {
			connection.close();
		}
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	response.setContentType("text/json,charset=utf-8");
	response.getWriter().write(res);
}

3. 在Servlat中直接调方法

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	String sql = "select * from student";
	
	//直接调用写好的JavaMysql类中的search方法
	String res = JavaMysql.search(sql);
	
	response.setContentType("text/json,charset=utf-8");
	response.getWriter().write(res);
}

4. 涉及到的知识点

  1. Class.forName("com.mysql.jdbc.Driver");:加载驱动的固定写法
  2. DriverManager:为数据库建立连接的
    • getConnection(String url, String user, String password)方法:使用用户名和密码建立连接
  3. Connection:连接类接口,用于执行sql语句
    • createStatement()方法:用于创建一个 Statement 对象,该对象用于向数据库发送并执行静态sql语句
  4. Statement:执行sql语句并返回结果的接口
    • 获取执行结果:
      • 查询返回ResultSet(结果集)
      • 更新返回int(受影响的行数)
    • executeQuery()方法:执行查找,返回ResultSet
    • executeUpdate()方法:执行更新(如 INSERT, UPDATE, DELETE),返回int
  5. ResultSet:表示从数据库查询返回的结果集(类似一个数据表格)
    • next()方法:获取下一行数据,返回true表示有数据
  6. substring(开始, 结束)方法:截取,用于截取字符串中的一部分,范围:左闭右开

二、删除数据库

  1. 删除流程与查找流程大致一样
  2. 执行sql的对象调用方法 执行sql语句,返回的是int受影响的行数
  3. 不需要处理结果
//删除
public static int delete(String sql) {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		String url="jdbc:mysql://localhost:3306/mysqltest";
		String user = "root";
		String password = "root";
		Connection connection = (Connection)DriverManager.getConnection(url, user, password);
		Statement statement = (Statement) connection.createStatement();
		int num = statement.executeUpdate(sql);
		if(statement!=null) {
			statement.close();
		}
		if(connection!=null) {
			connection.close();
		}
		return num;
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		return 0;
	}
}

三、添加/修改数据库

添加和修改的代码与删除是完全一样的

//添加
public static int add(String sql) {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		String url="jdbc:mysql://localhost:3306/mysqltest";
		String user = "root";
		String password = "root";
		Connection connection = (Connection)DriverManager.getConnection(url, user, password);
		Statement statement = (Statement) connection.createStatement();
		int num = statement.executeUpdate(sql);
		if(statement!=null) {
			statement.close();
		}
		if(connection!=null) {
			connection.close();
		}
		return num;
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		return 0;
	}
}
//修改
public static int update(String sql) {
	try {
		Class.forName("com.mysql.jdbc.Driver");
		String url="jdbc:mysql://localhost:3306/mysqltest";
		String user = "root";
		String password = "root";
		Connection connection = (Connection)DriverManager.getConnection(url, user, password);
		Statement statement = (Statement) connection.createStatement();
		int num = statement.executeUpdate(sql);
		if(statement!=null) {
			statement.close();
		}
		if(connection!=null) {
			connection.close();
		}
		return num;
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		return 0;
	}
}

四、精简代码

通过上面的代码可以得出有2个问题:

  • 有许多重复的代码,导致代码冗余
  • 针对查找有一点局限,查找代码中的处理结果写的是student表解析,但凡换一张表就出错

解决方案:

  • 将重复的加载驱动部分的代码单独拎出来,分装为一个类,后续可直接调用;
  • 动态获取字段:传数组存字段,读取字段存入到数组中

1. 分装加载驱动

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConnection {

	String driver = "com.mysql.jdbc.Driver";
	String url = "jdbc:mysql://localhost:3306/mysqltest";
	String user = "root";
	String password = "root";
	
	public Connection conn;

	public DBConnection() {

		try {
			Class.forName(driver);
			conn = (Connection) DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void close() {
		try {
			this.conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

2. 分装增删改查操作

import java.rmi.StubNotFoundException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MysqlUtil {

	//添加
	public static int add(String sql) {
        int i=0;
        DBConnection db = new DBConnection();// 创建数据库连接对象
        try {        
            PreparedStatement preStmt = (PreparedStatement) db.conn.prepareStatement(sql);//连接对象调用方法 创建执行sql的对象 获取结果集
            i=preStmt.executeUpdate();//执行sql语句
            preStmt.close();//关闭资源
            db.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return i;
    }

	//修改
    public static int update(String sql) {
        int i =0;
        DBConnection db = new DBConnection();
        try {
            PreparedStatement preStmt = (PreparedStatement) db.conn.prepareStatement(sql);
            i = preStmt.executeUpdate();
            preStmt.close();
            db.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return i;
    }
    
    //删除
    public static int del(String delstr) {
        int i=0;
        DBConnection db = new DBConnection();
        try {    
            PreparedStatement preStmt = (PreparedStatement) db.conn.prepareStatement(delstr);
            i=preStmt.executeUpdate();
            preStmt.close();
            db.close();
        } catch (SQLException e){
            e.printStackTrace();
        }
        return i;
    }

    //查数量
    public static int getCount(String sql) {
        int sum = 0;
        DBConnection db = new DBConnection();// 创建数据库连接对象
        try {
            Statement stmt = (Statement) db.conn.createStatement();//连接对象调用方法 创建执行sql的对象
            ResultSet rs = (ResultSet) stmt.executeQuery(sql);//执行sql的对象调用方法 执行sql语句 获取结果集
            while (rs.next()) {//遍历结果集每一行 累加第一列的值
                sum += rs.getInt(1);
            }
            rs.close();//关闭资源
            db.close();
        } catch (Exception e) {
        }
        return sum;
    }

    //查找
    public static String getJsonBySql( String sql,String[] colums){
        ArrayList<String[]> result = new ArrayList<String[]>();
        DBConnection db = new DBConnection();
        try {
            Statement stmt = (Statement) db.conn.createStatement();
            ResultSet rs = (ResultSet) stmt.executeQuery(sql);
            while(rs.next()){
                String[] dataRow = new String[colums.length];
                for( int i = 0; i < dataRow.length; i++ ) {
                    dataRow[i] = rs.getString( colums[i] );
                }
                result.add(dataRow);
            }
            rs.close();
            db.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return listToJson(result,colums);
    }

    public static String listToJson( ArrayList<String[]> list,String[] colums) {
    //分装格式代码
    }
}

涉及到的知识点

  1. prepareStatement()方法:可以防止sql注入,用法与statement用法一样
  2. sql注入:一种网络安全攻击技术,攻击者通过在应用程序的输入字段中插入恶意的SQL代码片段,从而操纵后端数据库查询,获取未授权访问或执行危险操作。

SQL注入

其类型有:

  • 未授权访问型
    -- 原始语句
    SELECT * FROM accounts WHERE account_id = '[用户输入]'
    -- 攻击输入
    1001' OR '1'='1
    -- 最终执行
    SELECT * FROM accounts WHERE account_id = '1001' OR '1'='1'
    -- 返回所有账户数据
    
  • 数据泄露行
    -- 攻击输入
    1001' UNION SELECT username, password FROM users --
    
    -- 最终执行
    SELECT * FROM accounts WHERE account_id = '1001' 
    UNION SELECT username, password FROM users --'
    -- 返回账户数据+所有用户凭证
    
  • 数据篡改型
    -- 攻击输入
    1001'; UPDATE users SET password = 'hacked' WHERE username = 'admin' --
    
    -- 最终执行
    SELECT * FROM accounts WHERE account_id = '1001'; 
    UPDATE users SET password = 'hacked' WHERE username = 'admin' --'
    -- 修改管理员密码
    
  • 数据库删除行
    -- 攻击输入
    1001'; DROP TABLE accounts --
    
    -- 最终执行
    SELECT * FROM accounts WHERE account_id = '1001'; DROP TABLE accounts --'
    -- 删除整个账户表
    

五、JDBC

是Java连接数据库的桥梁。
JDBC(Java Database Connectivity)是Java语言中用来规范客户端程序如何访问数据库的标准应用程序接口(API),它为Java开发者提供了与各种关系型数据库交互的统一方式。

JDBC核心组件

组件 作业 重要方法
DriverManager 管理数据库驱动 getConnection():建立与指定数据库的连接,参数有urluserpassword
Connection 表示与特定数据库的会话 createStatement():创建用于发送静态SQL语句的Statement对象
prepareStatement():创建预编译的PreparedStatement对象,防止 SQL注入
setAutoCommit():设置事务是否自动提交
commit():提交当前事务
Statement 用于执行静态SQL语句 executeQuery():执行查询语句,返回ResultSet对象
executeUpdate():执行DML/DDL语句,返回受影响的行数
execute():执行任意SQL语句,返回boolean表示结果类型;其中:true:执行的是查询语句,有ResultSet返回;false:执行的是更新语句或没有结果
PreparedStatement 预编译SQL语句,防止SQL注入 setInt():设置指定位置的整型参数
setString():设置指定位置的字符串参数
等参数绑定方法
ResultSet 表示数据库结果集的数据表 next():获取下一行数据
getString():获取字符串值
getInt():获取整数值
DataSource 更优的连接获取方式(连接池基础) getConnection():从连接池获取数据库连接
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐