文章目录
一、Java连接mysql数据库
1.1 流程
java连接mysql大致需要这六步:
- 导入驱动包:这里我使用的是mysql-connector-java-8.0.17.jar(
点击下载
),这个包连接mysql5.6,5.7,8.0版本都没问题。Class.forName("com.mysql.cj.jdbc.Driver");
- url和账户名密码 JDBC连接串:jdbc:mysql://<地址>:<端口>/<数据库>
- 获取连接:
DriverManager.getConnection(url, user, password);
- 执行sql的Statement对象:
connection.createStatement();
- 执行SQL
- 释放连接
1.2 一个测试连接的java程序
JdbcFirstDemo.java
packagecom.peng.less01;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassJdbcFirstDemo{publicstaticvoidmain(String[] args)throwsClassNotFoundException,SQLException{// 1.导入驱动类Class.forName("com.mysql.cj.jdbc.Driver");// 2.用户信息和urlString url ="jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false";String user ="root";String password ="12345678";// 3.获取连接Connection conn =DriverManager.getConnection(url, user, password);// 4.执行SQL的对象Statement sta = conn.createStatement();// 5.执行SQLString sql ="select * from account";ResultSet rs = sta.executeQuery(sql);while(rs.next()){System.out.println("id= "+ rs.getObject("id"));System.out.println("name= "+ rs.getObject("name"));System.out.println("money= "+ rs.getObject("money"));System.out.println("=========================================");}// 6.释放连接
rs.close();
sta.close();
conn.close();}}
这里使用的是VScode,connector包放到了lib目录下,代码放在了src/com/peng/less01下。
执行结果如下,显示了shop.account表下面的三条记录。
二、优化:创建一个工具类
2.1 存在的问题
1、JDBC连接串,用户名,密码等都存在于代码中,需要进行解耦
2、创建连接,释放连接这些操作都是固定的,没必要每次都重复写这些代码(创建函数解决)
2.2 创建配置文件和工具类
src/db.properties 文件中记录driver,url,user,password
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/shop?useUnicode=true&characterEncoding=utf8&useSSL=false
user=root
password=12345678
src/com/peng/less02/utils/JdbcUtils.java 工具类:读取properties配置文件
自动读取配置信息,加载mysql驱动。
packagecom.peng.less02.utils;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;importjava.util.Properties;// 这是一个工具类,用来减少重复操作publicclassJdbcUtils{privatestaticString driver =null;privatestaticString url =null;privatestaticString user =null;privatestaticString password =null;static{try{// 读取db.propertiesInputStream in =JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");Properties properties =newProperties();
properties.load(in);
driver = properties.getProperty("driver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");// 加载驱动Class.forName(driver);}catch(Exception e){
e.printStackTrace();}}// 创建连接publicstaticConnectiongetConnection()throwsSQLException{returnDriverManager.getConnection(url,user,password);}// 释放连接publicstaticvoidreleaseConnection(Connection conn,Statement sta,ResultSet rs){if(rs !=null){try{
rs.close();}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}}if(sta !=null){try{
sta.close();}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}}if(conn !=null){try{
conn.close();}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}}}}
2.3 测试使用工具类进行CRUD操作
**
测试插入操作
**
src/com/peng/less02/TestInsert.java
packagecom.peng.less02;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;importcom.peng.less02.utils.JdbcUtils;publicclassTestInsert{publicstaticvoidmain(String[] args){Connection conn =null;Statement sta =null;ResultSet rs =null;try{
conn =JdbcUtils.getConnection();
sta = conn.createStatement();String sql ="insert into account(`id`,`name`,`money`) values(4,'药水哥',4698888)";int i = sta.executeUpdate(sql);if(i >0){System.out.println("插入成功!");}}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}finally{JdbcUtils.releaseConnection(conn, sta, rs);}}}
**
测试更新操作
**
src/com/peng/less02/TestUpdate.java
packagecom.peng.less02;importjava.sql.*;importcom.peng.less02.utils.JdbcUtils;publicclassTestUpdate{publicstaticvoidmain(String[] args){Connection conn =null;Statement sta =null;try{
conn =JdbcUtils.getConnection();
sta = conn.createStatement();String sql ="update account set `money`=238888 where id=3";int i = sta.executeUpdate(sql);if(i >0){System.out.println("更新成功");}}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}finally{JdbcUtils.releaseConnection(conn, sta,null);}}}
**
测试读取操作
**
packagecom.peng.less02;importjava.sql.*;importcom.peng.less02.utils.JdbcUtils;publicclassTestSelect{publicstaticvoidmain(String[] args){Connection conn =null;Statement sta =null;ResultSet rs =null;try{
conn =JdbcUtils.getConnection();
sta = conn.createStatement();String sql ="select * from account";
rs = sta.executeQuery(sql);while(rs.next()){System.out.println("id= "+ rs.getInt("id"));System.out.println("name= "+ rs.getString("name"));System.out.println("money= "+ rs.getObject("money"));System.out.println("======================================================");}}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}finally{JdbcUtils.releaseConnection(conn, sta, rs);}}}
三、SQL注入问题
这里写一个登录认证程序,如果账号,密码输入正确则允许登录。为了测试,这里的允许登录改为输出账号密码。
还使用前面写的JdbcUtils工具类
可以看到,这里我输入的用户名/密码是:’ or '1=1****’ or '1=1
然后输出了user表中的所有数据,这明显是不合法的。存在sql注入的问题
问题就在于这段代码,sql是拼接而成的。
String sql ="select * from user where `username`='"+ username +"' and `password`='"+ password +"'";
拼接的sql为:
select * from user where `username`='' or '1=1' and `password`='' or '1=1';
3.1 SQL注入示例
SqlInjection.java
packagecom.peng.less02;importcom.peng.less02.utils.JdbcUtils;importjava.sql.*;publicclassSqlInjection{publicstaticvoidmain(String[] args){login("' or '1=1","' or '1=1");}// 登录功能publicstaticvoidlogin(String username,String password){Connection conn =null;Statement sta =null;ResultSet rs =null;try{
conn =JdbcUtils.getConnection();
sta = conn.createStatement();//这段代码中sql是变量拼接而成的String sql ="select * from user where `username`='"+ username +"' and `password`='"+ password +"'";
rs = sta.executeQuery(sql);//输入正确的账号密码就能够登录,这里为了测试就(输入正确输出账号密码)while(rs.next()){System.out.println("id= "+ rs.getInt("id"));System.out.println("username= "+ rs.getString("username"));System.out.println("password= "+ rs.getObject("password"));System.out.println("======================================================");}}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}finally{JdbcUtils.releaseConnection(conn, sta, rs);}}}
四、使用PreparedStatement防止SQL注入
- 使用PreparedStatement,防止SQL注入,同时对于执行多次的SQL更加高效
PreparedStatement,
对sql进行了预编译
,传入的参数只会被当作字符串来处理,而不会像前面对sql进行了拼接。
**
流程如下:
**
先编写sql --> 进行预编译 --> 增加sql参数值 --> 执行sql
SqlInjection.java
packagecom.peng.less03;importcom.peng.less02.utils.JdbcUtils;importjava.sql.*;publicclassSqlInjection{publicstaticvoidmain(String[] args){// login("'' or 1=1", "'' or 1=1");login("张三","zhangsan");}// 登录功能publicstaticvoidlogin(String username,String password){Connection conn =null;PreparedStatement psta =null;ResultSet rs =null;try{
conn =JdbcUtils.getConnection();//这里使用 ? 占位符来代替String sql ="select * from user where `username`=? and `password`=?";//使用PreparedStatement,防止SQL注入,同时对于执行多次的SQL更加高效
psta = conn.prepareStatement(sql);
psta.setString(1,username);
psta.setObject(2,password);
rs = psta.executeQuery();//输入正确的账号密码就能够登录,这里为了测试就(输入正确输出账号密码)while(rs.next()){System.out.println("id= "+ rs.getInt("id"));System.out.println("username= "+ rs.getString("username"));System.out.println("password= "+ rs.getObject("password"));System.out.println("======================================================");}}catch(SQLException e){// TODO Auto-generated catch block
e.printStackTrace();}finally{JdbcUtils.releaseConnection(conn, psta, rs);}}}
五、JDBC操作事务
和用sql执行事务类似,创建连接后
setAutoCommit(false)
,最后
commit()
,失败则
rollback()
。
注意:rollback()部分可以不用写,事务失败会自动回滚。
TestTransaction.java
packagecom.peng.less04;importjava.sql.*;// 仍然使用前面写的JdbcUtils工具类importcom.peng.less02.utils.JdbcUtils;publicclassTestTransaction{publicstaticvoidmain(String[] args){Connection conn =null;PreparedStatement pst =null;try{
conn =JdbcUtils.getConnection();// 关闭自动提交,开启事务
conn.setAutoCommit(false);//模拟一个转账事务,A向大帅哥转账100块String sql1 ="update account set `money`=money - 100 where `name`='A'";
pst = conn.prepareStatement(sql1);
pst.executeUpdate();// int x = 1/0;String sql2 ="update account set `money`=money + 100 where `name`='大帅哥'";
conn.prepareStatement(sql2).executeUpdate();
conn.commit();System.out.println("Success!");}catch(SQLException e){// TODO Auto-generated catch blocktry{// rollback()可以不用写,失败的话会自动回滚
conn.rollback();}catch(SQLException e1){// TODO Auto-generated catch block
e1.printStackTrace();}
e.printStackTrace();}finally{JdbcUtils.releaseConnection(conn, pst,null);}}}
版权归原作者 银痕 所有, 如有侵权,请联系我们删除。