JDBC链接MySql及查询操作
目录
一:准备工作
使用JDBC前需前往MySql官网下载JDBC提供的类文件,下载箭头所指文件并解压,在你的IDEA项目中创建lib文件,并将其解压后的.jar文件放入,并将其中jar文件导入你的工程文件模块即可。最后再创建一个自己的数据库(本篇用mydb作为样例)https://dev.mysql.com/downloads/connector/j/
安装成功后我选择创建一个名为"mydb"的数据库,其中有一个students表储存了学生信息


二:连接数据库的简单流程
大致分为以下6步:
2.1:注册驱动
使用registerDriver方法进行注册,
DriverManager.registerDriver(new Driver());
2.2:获取连接
getConnection(String url,String user,String password)
Connection connection=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","222222");
//url写法:"jdbc:数据库名://数据库ip,是本机就填127.0.0.1:端口(默认3306)/目标数据库"
//本机例子:jdbc:mysql://127.0.0.1:3306/mydb 或可简写为 jdbc:mysql:///mydb
2.3:创建发送SQL语句对象
Statement statement=connection.createStatement();
2.4:发送sql语句,并获取返回结果
String inf="select * from students;";
ResultSet resultSet=statement.executeQuery(inf);
2.5:结果集解析
其所返回的resultSet是一个将数据打包成的类,其中提供了许多定位数据的方法。.next方法会根据下一条的数据内容是否为空来返回boolean类型。.get参数()方法提供了使用脚标返回列元素,使用当前列名返回列元素这两种方法来返回数据。例如目前表中有这样的数据,并且数据解析代码如下
while(resultSet.next()){
int a=resultSet.getInt(1);
String b=resultSet.getString("name");
int c=resultSet.getInt(3);
String d=resultSet.getString("residence");
System.out.printf("%d %s %d %s\n",a,b,c,d);
}
结果如下:

2.6:资源关闭
resultSet.close();
statement.close();
connection.close();
三:上述操作存在的问题及改进
3.1:注册驱动操作冗余
通关观察DriverManager.registerDriver(new Driver());中的.register()方法和Driver()方法的源代码可见
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}//Driver方法
public static void registerDriver(java.sql.Driver driver)
throws SQLException {
registerDriver(driver, null);
}//registerDriver方法
当执行上述语句时,执行了两次注册操作,并且在Driver()方法中,注册操作是在静态代码块中,因此我们改为使用反射中的方法.Class.forName("此处传入数据库的Driver方法的类名");用此方法来注册还易于多数据库的更改
Class.forName("com.mysql.cj.jdbc.Driver");//使用反射进行注册驱动
3.2:Statement语句的危险性
我们传入sql语句时,有可能是经过拼接后才传入的,此时如果传入特定字符串会导致sql语句变为一串特殊的动态判断语句,这样可能会引发sql注入攻击导致数据泄漏。
解决方案:使用PreparedStatement(预编译的Statement)代替Statement
使用方法:
先定义sql语句,再传入PreparedStatement进行预处理,注意这里的sql语句不同于上述sql语句的规范,当我们想对sql语句进行拼接操作时,拼接的内容需要用'?'来进行代替,例如想要查询住在一号楼并且分数小于90的同学的信息
String sql="Select * from students where residence = ? and score< ?";
//声明查询语句,关键词用'?'代替
PreparedStatement preparedStatement= connection.prepareStatement(sql);
//此句与Statement相似,并且要先传入语句进行预处理
preparedStatement.setObject(1,"一号楼");
preparedStatement.setObject(2,90);
//.setObject(int Index,Object x)Index传入的是第n个参数的位置,位置从1开始
ResultSet resultSet=preparedStatement.executeQuery();
由上述代码可知,PreparedStatement发送sql的位置和Statement不同,因为上面建立连接时已经传入。
四:正确查询样例
有一个学生表,先想查询分数小于90并且住在一号楼的学生信息。数据库为mydb,用户为root,密码为222222
public static void main(String[] args)throws Exception{
//注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");//会自动激活目标类的静态代码区
//获取连接
Connection connection= DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb","root","222222");
//创建连接对象
String sql="Select * from students where residence = ? and score< ?";
PreparedStatement preparedStatement= connection.prepareStatement(sql);
preparedStatement.setObject(1,"一号楼");
preparedStatement.setObject(2,90);
//获取结果
ResultSet resultSet=preparedStatement.executeQuery();
//解析结果集
while(resultSet.next()){
int a=resultSet.getInt(1);
String b=resultSet.getString("name");
int c=resultSet.getInt(3);
String d=resultSet.getString("residence");
System.out.printf("%d %s %d %s\n",a,b,c,d);
}
//进行回收
resultSet.close();
preparedStatement.close();
connection.close();
}
返回结果如下: