JDBC
前言
在学习了SQL语句后,我们肯定会思考如何使用数据库里的数据。这个时候,我们便要学习JDBC来将数据库与JAVA结合在一块。
正题
什么是JDBC?
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口。
JDBC的主要用途
- 与数据库建立连接
- 发送 SQL 语句
- 处理结果
数据库驱动
在学习JDBC之前,我们必须了解一个东西,驱动。
驱动:两个设备(两个应用)之间通信的桥梁。
JDBC的开发步骤
- 加载驱动
- 获取连接
- 基本操作(CRUD)
- 释放资源
使用JDBC的准备工作
1.创建一个maven项目(当然你也可以不用这种方法,但maven在开发中最为方便)
【创建方式请看我之前的博客:利用Maven进行导jar包】
2.导入mysql的jar包
<dependencies> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies>
完成以上的操作,我们便可以开始进行JDBC的学习了。
JDBC的简单例子(先了解一下整体的框架,后面会相应的解释以及简化)
package com.jdbc.demo01; import org.junit.Test; import java.sql.*; /** * * JDBC的入门程序 * @author Charles * */ public class JDBCdemo1 {
@Test public void demo01() throws ClassNotFoundException, SQLException { // 1.加载驱动 Class.forName("com.jdbc.Driver"); // 2.获得连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root" , "1234"); // 3.基本操作:执行SQL // 3.1获得执行SQL语句的对象 Statement statement = conn.createStatement(); // 3.2编写SQL语句: String sql = "select * from user"; // 3.3执行SQL: ResultSet rs = statement.executeQuery(sql); // 3.4遍历结果集 while (rs.next()){ System.out.println(rs.getInt(("id")+ " ")); System.out.println(rs.getInt(("username")+ " ")); System.out.println(rs.getInt(("password")+ " ")); System.out.println(rs.getInt(("nickname")+ " ")); System.out.println(rs.getInt(("age"))); System.out.println(); } // 4.释放资源 rs.close(); statement.close(); conn.close(); } }
接下来我来介绍一下上面代码的含义:
// 1.加载驱动,双引号里面的内容一般是标准 Class.forName("com.jdbc.Driver");
此时,你或许会好奇,不是注册驱动吗,为什么代码是加载驱动。
首先,我们来看看JAVA的API中Driver注册驱动的介绍
这种方式的确可以完成驱动的注册,但是实际开发中并不会这么做。
原因:
如果需要注册驱动,就会使用DirverManager.registerDriver(new Driver()); ,但是在查询源代码的时候,我们发现源代码中有一段静态代码块已经调用了注册驱动的方法。因此,如果我们再手动调用注册,就会导致驱动被注册两次。
所以调用 Class.forName 将自动将加载驱动程序类。(具体的原理可以查看一些API文档)
②:Connection conn = DriverManager.getConnection(url, user, password);
// 2.获得连接 Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root", "1234");
参数介绍:
- url:与数据库连接的路径
- user:与数据库连接的用户名
- password:与数据库连接的密码
url:
"jdbc:mysql://localhost:3306/web_test3"
- jdbc:连接数据库的协议
- mysql:是jdbc的子协议
- localhost:连接的Mysql数据库服务器的主机地址【本机:localhost,非本机:连接主机的IP地址】
- 3306:Mysql数据库服务器的端口号
- web_test3:数据库名称
commit
rollback
接下来我们来看看Statement的详细操作:
作用:①执行SQL ②执行批处理
①:常用的执行SQL方法: 主要使用的是后两个
- boolean execute(String sql)
执行查询,修改,添加,删除的SQL语句
- ResultSet executeQuery(String sql)
执行查询(Select 语句)
- int executeUpdate(String sql)
执行修改,添加,删除的SQL语句
②:常用的执行批处理的方法
addBatch
clearBatch
executeBatch
结果集的获取可以使用: getxxx(); 通常都会有重载的方法。
getxxx(String columnName);
if(rs != null){ try{ rs.close(); } catch (SQLException e){ e.printStackTrace(); } rs = null; } if(statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if(conn != null){ try{ conn.close(); } catch (SQLException e){ e.printStackTrace(); } conn = null; }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; try{ // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得连接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234); // 执行操作 // 创建执行SQL语句对象 statement = conn.createStatement(); // 编写SQL语句 String sql = "insert into user values (null, ‘eee‘, ‘123‘, ‘Jack‘, 21)"; // 执行SQL语句 int num = statement.executeUpdate(sql); if (num > 0){ System.out.println("保存用户成功!"); } }catch (Exception e){ e.printStackTrace(); }finally { // 释放资源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; try{ // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得连接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 执行操作 // 创建执行SQL语句对象 statement = conn.createStatement(); // 编写SQL语句 String sql = "update user set password=‘2222‘,nickname=‘biubiu‘ where id=6"; // 执行SQL语句 int num = statement.executeUpdate(sql); if (num > 0){ System.out.println("修改用户成功!"); } }catch (Exception e){ e.printStackTrace(); }finally { // 释放资源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; try{ // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得连接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 执行操作 // 创建执行SQL语句对象 statement = conn.createStatement(); // 编写SQL语句 String sql = "delete from user where id=6"; // 执行SQL语句 int num = statement.executeUpdate(sql); if (num > 0){ System.out.println("删除用户成功!"); } }catch (Exception e){ e.printStackTrace(); }finally { // 释放资源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; ResultSet rs = null; try{ // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得连接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 执行操作 // 创建执行SQL语句对象 statement = conn.createStatement(); // 编写SQL语句 String sql = "select * from user"; // 执行SQL语句 rs = statement.executeQuery(sql); while(rs.next()){ System.out.println(rs.getInt(("id")+ " ")); System.out.println(rs.getInt(("username")+ " ")); System.out.println(rs.getInt(("password")+ " ")); System.out.println(rs.getInt(("nickname")+ " ")); System.out.println(rs.getInt(("age"))); System.out.println(); } }catch (Exception e){ e.printStackTrace(); }finally { // 释放资源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
package com.charles.sql; import org.junit.*; import java.sql.*; public class Demo01 { @Test public void demo01(){ Connection conn = null; Statement statement = null; ResultSet rs = null; try{ // 注册驱动 Class.forName("com.mysql.jdbc.Driver"); // 获得连接 conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "1234"); // 执行操作 // 创建执行SQL语句对象 statement = conn.createStatement(); // 编写SQL语句 String sql = "select * from user where id=1"; // 执行SQL语句 rs = statement.executeQuery(sql); if(rs.next()){ System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+re.getString("password")); } }catch (Exception e){ e.printStackTrace(); }finally { // 释放资源 if (statement != null){ try{ statement.close(); } catch (SQLException e){ e.printStackTrace(); } statement = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } } }
目的:包装成工具类后,能够更方便地使用JDBC,减少不必要的工作量
package org.charl; import java.sql.*; /** * JDBC工具类 * @author Charles */ public class Demo { // 默认设置 public static final String driverClassName; public static final String url; public static final String username; public static final String password; static { driverClassName = "com.mysql.jdbc.Driver"; url = "jdbc:mysql:///web_test3"; username = "root"; password = "1234"; } // 注册驱动类 public static void loadDriver(){ try { Class.forName(driverClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 获得连接 public static Connection getConnection(){ Connection conn = null; try { loadDriver(); conn = DriverManager.getConnection(url,username,password); } catch (SQLException e) { e.printStackTrace(); } return conn; } // 资源释放 public static void release(Statement st,Connection conn){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } public static void release(Statement st,Connection conn, ResultSet rs){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } rs = null; } } }
在工具类中解析属性文件
SQL注入漏洞的解决方法
采用PreparedStatement对象解决SQL注入漏洞问题。该对象将SQL预先进行编译,使用‘?‘作为占用符。‘?‘所代表的内容是SQL所固定。如果再次传入变量(包括SQL的关键字),这个时候也不会识别这些关键字。
具体操作:
package com.charles.sql; import java.sql.*; /*** * @return * @author Charles */ public class Demo02 { public boolean login(String username, String password){ Connection conn = null; PreparedStatement preparedStatement = null; ResultSet rs = null; boolean flag = false; try{ conn = org.charl.Demo.getConnection(); String sql = "select * from user where username = ? and password = ?"; preparedStatement = conn.prepareStatement(sql); // 设置参数 preparedStatement.setString(1,username); preparedStatement.setString(2,password); rs = preparedStatement.executeQuery(); if (rs.next()){ flag = true; } } catch (SQLException e){ e.printStackTrace(); } finally { org.charl.Demo.release(preparedStatement,conn,rs); } return flag; } }
接下来展示一下比较完整的实例:
【里面包含了PreparedStatement等内容,之前的案例看不懂没关系,这个案例供大家参考】
数据库web_test4中user表原先的信息
工具类代码
package org.charl; import java.sql.*; import java.util.Properties; /** * JDBC工具类 * @author Charles */ public class Demo { // 默认设置 public static final String driverClassName; public static final String url; public static final String username; public static final String password; static { driverClassName = "com.mysql.jdbc.Driver"; url = "jdbc:mysql:///web_test4?rewriteBatchedStatements=true?characterEncoding=utf-8"; username = "root"; password = "1234"; } // 注册驱动类 public static void loadDriver(){ try { Class.forName(driverClassName); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // 获得连接 public static Connection getConnection(){ Connection conn = null; try { loadDriver(); conn = DriverManager.getConnection(url,username,password); } catch (SQLException e) { e.printStackTrace(); } return conn; } // 资源释放 public static void release(Statement st,Connection conn){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } } public static void release(Statement st,Connection conn, ResultSet rs){ if (st != null){ try{ st.close(); } catch (SQLException e){ e.printStackTrace(); } st = null; } if (conn != null){ try { conn.close(); }catch (SQLException e){ e.printStackTrace(); } conn = null; } if (rs != null){ try { rs.close(); }catch (SQLException e){ e.printStackTrace(); } rs = null; } } }
执行主代码
package com.charles.sql; import org.junit.Test; import java.sql.*; public class Demo03 { @Test public void Test(){ long begin = System.currentTimeMillis(); Connection conn = null; PreparedStatement preparedStatement = null; ResultSet rs = null; try{ // 注册驱动 + 获得连接 conn = org.charl.Demo.getConnection(); // 编写SQL语句 String sql = "insert into user values(null,?)"; // 预编译 preparedStatement = conn.prepareStatement(sql); for (int i =1;i<10000;i++){ preparedStatement.setString(1,"name"+i); // 添加到批处理 preparedStatement.addBatch(); // 执行批处理 if (i % 1000 == 0){ preparedStatement.executeBatch(); // 进行清空防止数据溢出 preparedStatement.clearBatch(); } } }catch (Exception e){ e.printStackTrace(); }finally { // 释放资源 org.charl.Demo.release(preparedStatement,conn,rs); } long end = System.currentTimeMillis(); System.out.println("耗时:"+ (end - begin) + "ms"); } }
执行成功后:
控制台
此时user表中的数据
小结
以上就是JDBC入门的介绍,当然在刚学习JDBC的时候,肯定会出现许多错误,这些错误或许一时间会让你抓狂,但请耐心地解决,相信后面收获肯定满满的。
加油!
时间:2020-04-02 20:57:18