Java连接MySQL数据库
Java连接数据库目录
- 一、查找数据库
- 1.写入到普通的Java文件中
- 2. 写入到servlet文件中
- 3. 在Servlat中直接调方法
- 4. 涉及到的知识点
- 二、删除数据库
- 三、添加/修改数据库
- 四、精简代码
- 1. 分装加载驱动
- 2. 分装增删改查操作
- 涉及到的知识点
- 五、JDBC
- JDBC核心组件
一、查找数据库
1.写入到普通的Java文件中
- 放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
- MySQL版本为5.几的可以使用
- 加载驱动:固定写法,会报错,原因有二:
- 忘记放入响应的jar包
- 异常,有两种处理方式
throws ClassNotFoundException
:异常抛出,抛给它的调用者->main方法,main方法还不做处理,继续向上抛出try{}catch(){e.printStackTrace();}
:自己捕获,执行try中的操作,如果出错,catch会捕获没有找到的异常
- 驱动管理类调方法进行连接:
- 接受参数url、user、password,数据库不一定存在,会报异常,也进行捕获
- 返回一个连接类接口
Connection
,由于DriverManager
是父类,Connection
是子类,需要强制转换
- 连接对象调用方法 创建执行sql的对象:返回
Statement
,由于Connection
是父类,Statement
是子类,需要强制转换 - 执行sql的对象调用方法 执行sql语句:返回
ResultSet
结果集 - 处理结果:获取返回结果中的所有字段;可以用字符串拼接,将返回的数据分装为json格式,装到数组中
- 注意:json格式可以使用json解析工具,将想要的字段写好,直接复制过来即可,这样不易出错
- 关闭资源:倒着关闭,后开辟的先关闭;做判断,如果不为空,就让这个对象关闭
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 blocke.printStackTrace();return "";}}
2. 写入到servlet文件中
- 写入到
doGet
中类中 - sql会报错,是因为在main方法中中传的参数,所有要加一个sql变量
- 返回
return
会报错,是因为在servlet
中,返回数据使用的是response
,使用getWriter().write()
写入返回的数据 - 变量
res
写在了try
中,所有将其写入到外面 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 blocke.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. 涉及到的知识点
Class.forName("com.mysql.jdbc.Driver");
:加载驱动的固定写法DriverManager
:为数据库建立连接的getConnection(String url, String user, String password)
方法:使用用户名和密码建立连接
Connection
:连接类接口,用于执行sql语句createStatement()
方法:用于创建一个Statement
对象,该对象用于向数据库发送并执行静态sql语句
Statement
:执行sql语句并返回结果的接口- 获取执行结果:
- 查询返回
ResultSet
(结果集) - 更新返回
int
(受影响的行数)
- 查询返回
executeQuery()
方法:执行查找,返回ResultSet
executeUpdate()
方法:执行更新(如INSERT
,UPDATE
,DELETE
),返回int
- 获取执行结果:
ResultSet
:表示从数据库查询返回的结果集(类似一个数据表格)next()
方法:获取下一行数据,返回true
表示有数据
substring(开始, 结束)
方法:截取,用于截取字符串中的一部分,范围:左闭右开
二、删除数据库
- 删除流程与查找流程大致一样
- 执行sql的对象调用方法 执行sql语句,返回的是
int
受影响的行数 - 不需要处理结果
//删除
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 blocke.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 blocke.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 blocke.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) {//分装格式代码}
}
涉及到的知识点
prepareStatement()
方法:可以防止sql注入,用法与statement
用法一样- 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() :建立与指定数据库的连接,参数有url 、user 、password |
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() :从连接池获取数据库连接 |