JDBC:Java连接MySQL数据库
·
Java连接数据库目录
一、查找数据库
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 block
e.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 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. 涉及到的知识点
Class.forName("com.mysql.jdbc.Driver");:加载驱动的固定写法DriverManager:为数据库建立连接的getConnection(String url, String user, String password)方法:使用用户名和密码建立连接
Connection:连接类接口,用于执行sql语句createStatement()方法:用于创建一个Statement对象,该对象用于向数据库发送并执行静态sql语句
Statement:执行sql语句并返回结果的接口- 获取执行结果:
- 查询返回
ResultSet(结果集) - 更新返回
int(受影响的行数)
- 查询返回
executeQuery()方法:执行查找,返回ResultSetexecuteUpdate()方法:执行更新(如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 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) {
//分装格式代码
}
}
涉及到的知识点
prepareStatement()方法:可以防止sql注入,用法与statement用法一样- 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():建立与指定数据库的连接,参数有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():从连接池获取数据库连接 |
更多推荐
所有评论(0)