20.java-JDBC连接mysql数据库详解
1.jdbc介绍
jdbc(java database connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成。
jdbc需要用到的类和接口有:
drivermanager、connection、statement、resultset
2. mysql-connector-java下载
本机的mysql版本是5.7.26 win32的,所以本章访问mysql都以该版本为例:
然后进入下载mysql-connector-java.jar包,用于连接mysql
如下图所示,只有8.0.19版本,那我们下载它就好了,反正不管64位还是32位都能访问:
下载解压后,就有个mysql-connector-java-8.0.19.jar:
接下来就来测试,能不能访问
3.jdbc使用过程
3.1 通过drivermanager. registerdriver(driver driver)来注册驱动程序
需要注意,new driver的时候,需要选择com.mysql.cj.jdbc.driver:
因为com.mysql.jdbc.driver已经被弃用了.
ps:也可以直接将drivermanager. registerdriver(driver driver)改为:
class.forname("com.mysql.cj.jdbc.driver"); //加载一下这个类就可以注册驱动,因为mysql driver类的静态代码块中已经调用了registerdriver()来注册驱动程序.
3.2 然后通过 connection drivermanager.getconnection(string url, string user, string password)来连接数据库,并获取connection对象
url: 填入“jdbc:子协议://ip地址:端口号/数据库名” ,如果是mysql则填入“jdbc:mysql://localhost:3306/数据库名”
针对mysql-connector-java-8.0以上的版本,则还要追加"?characterecoding=utf-8&usessl=false&servertimezone=utc&rewritebatchedstatements=true"
username:mysql用户名
password:mysql密码
3.3 通过connection对象获取statement对象
statement statement = connection.createstatement();
3.4 通过statement对象的executequery(string)来执行查询sql语句,并返回resultset数据库结果集
比如:
resultset resultset = statement. executequery("select * from student"); //获取student表里的数据
除此之外还有int executeupdate(string sql)方法.用来实现insert、update 或 delete 语句,返回值表示执行sql语句之后影响到的数据行数 (后面示例有讲)
3.5 然后通过resultset来读出query内容
resultset常用方法如下:
boolean first(); //移到内容第一行数据处 boolean last(); //移到内容最后一行数据处 int getrow() ; //获取当前光标处于的行号 boolean islast() //获取光标是否位于此 resultset 对象的最后一行。 boolean next(); //移到下一行数据处,然后就可以通过getxxx()获取完当前一行数据后,则通过next()来移动到下行继续getxxx(),直到next()返回为false为止 boolean previous(); //移到上一行数据处 string getstring(string columnlabel); //获取当前一行的columnlabel列名的内容 string getstring(int columnindex); //获取当前一行的第columnindex列的内容,第一列是从1开始的. string getint (string columnlabel); //获取当前一行的columnlabel列名的内容 string getint(int columnindex); //获取当前一行的第columnindex列的内容,第一列是从1开始的. //...除此之外,还有getfloat(),getlong(),getshort(),geturl(),getboolean(),getrowid()
ps:获取到resultset后,必须先next()一次才能getxxx(),来获取内容
3.6 访问结束后,释放mysql资源(毕竟mysql连入个数是有限的)
try { if(resultset!=null){ resultset.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if(statement!=null){ statement.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if(connection!=null){ connection.close(); } } catch (sqlexception e) { e.printstacktrace(); }
4.本章要访问的数据库以students为例:
5.首先来写jdbcutils工具类
jdbcutils工具类里主要写getconnection(),releaseresc()这两个类,这样避免后续的重复代码产生.
jdbcutils.java代码如下所示:
public class jdbcutils { private static string driver; private static string url; private static string user; private static string pwd; static{ driver = "com.mysql.cj.jdbc.driver"; url = "jdbc:mysql://localhost:3306/students?characterecoding=utf-8&" + "usessl=false&servertimezone=utc&rewritebatchedstatements=true"; user = "root"; pwd = "sql"; } //获取一个链接mysql的connection对象 static public connection getconnection(){ try { class.forname(driver); connection connection = drivermanager.getconnection(url,user,pwd); return connection; } catch (exception e) { e.printstacktrace(); return null; } } /** * 释放mysql资源(毕竟mysql连入个数是有限的) * @param resultset 结果集 * @param statement * @param connection 链接 */ public static void releaseresc(resultset resultset, statement statement, connection connection) { try { if(resultset!=null){ resultset.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if(statement!=null){ statement.close(); } } catch (sqlexception e) { e.printstacktrace(); } try { if(connection!=null){ connection.close(); } } catch (sqlexception e) { e.printstacktrace(); } } }
6.数据库查询示例
查询所有学生的信息:
@test public void jdbcquery(){ resultset resultset = null; statement statement = null; connection connection = null; try { connection = jdbcutils.getconnection(); //通过jdbcutils获取connection statement = connection.createstatement(); string sql = "select * from student"; resultset = statement.executequery(sql); while(resultset.next()){ string name = resultset.getstring("name"); string score = resultset.getstring("score"); string classs = resultset.getstring("class"); system.out.println("姓名:"+name+" 成绩:"+score+" 班级:"+classs); } } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); }finally { jdbcutils.releaseresc(resultset, statement, connection); //释放资源 } }
打印如下所示:
7.数据库插入示例
@test public void jdbcinser(){ resultset resultset = null; statement statement = null; connection connection = null; try { connection = jdbcutils.getconnection(); statement = connection.createstatement(); string name = "小f"; int score = 99; string classs = "初2-4班"; string sql = "insert into student(name,score,class) " +" values('"+name+"','"+string.valueof(score)+"','"+classs+"')"; int result = statement.executeupdate(sql); //executeupdate:用来实现insert、update 或 delete 语句,返回值表示执行sql语句之后影响到的数据行数 system.out.println("插入了"+result+"条数据"); } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); }finally { jdbcutils.releaseresc(resultset, statement, connection); //释放资源 } }
运行打印:
查看数据库:
8.数据库更新示例
将所有低于60分的同学的成绩改为0:
@test public void jdbcupdate(){ resultset resultset = null; statement statement = null; connection connection = null; try { connection = jdbcutils.getconnection(); statement = connection.createstatement(); string sql = "update student set score='0' where score<60"; int result = statement.executeupdate(sql); //executeupdate:用来实现insert、update 或 delete 语句,返回值表示执行sql语句之后影响到的数据行数 system.out.println("更新了"+result+"条数据"); } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); }finally { jdbcutils.releaseresc(resultset, statement, connection); //释放资源 } }
查看数据库:
9.sql 注入攻击
statement采取直接编译 sql 语句的方式,扔给数据库去执行,所以很容易进行被sql注入攻击.
比如:
我们登陆执行时需要执行:
statement.executequery("select id from users where name ='"+username+"' and password = '"+password+"'");
而黑客则将字符串直接改为:
statement.executequery("select id from users where name ='"+username+"' or '1==1' and password = '"+password+"'");
就可以直接乱输入密码也能实现登录了,所以java中提供了另一个类preparedstatement, 采用"?"占位符预编译,再填充参数,用来避免sql注入攻击.
preparedstatement类介绍
采用"?"占位符预编译,再填充参数,然后通过setxxx()来填充参数.比如setstring():
setstring(int parameterindex, string x); //向第parameterindex个占位符填入x内容 // parameterindex:第一个?占位符是1,第二个是2.... //...除了该方法之外,还有setfloat(),setlong(),setboolean()....等等
修改登录界面之preparedstatement使用如下所示:
public static boolean login(string username,string password){ connection connection = jdbcutils.getconnection(); //获取 try { string sql = "select id from users where username =? and password = ?"; //要运行的sql语句,通过?来替换登录账号和密码 preparedstatement preparedstatement = connection.preparestatement(sql); //第一个? 用username字符串去替换 preparedstatement.setstring(1, username); //第二个? 用password字符串去替换 preparedstatement.setstring(2, password); resultset resultset = preparedstatement.executequery(); return resultset.next(); //有值则返回true,否则返回false; } catch (sqlexception e) { e.printstacktrace(); return false; } }