多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[TOC] ## 一、JDBC连接 使用JDBC时,我们先了解什么是Connection。Connection代表一个JDBC连接,它相当于Java程序到数据库的连接(通常是TCP连接)。打开一个Connection时,需要准备URL、用户名和口令,才能成功连接到数据库。 URL是由数据库厂商指定的格式,例如,MySQL的URL是: <br> ~~~ jdbc:mysql://<hostname>:<port>/<db>?key1=value1&key2=value2 ~~~ <br> 假设数据库运行在本机`localhost`,端口使用标准的`3306`,数据库名称是`learnjdbc`,那么URL如下: ~~~ jdbc:mysql://localhost:3306/learnjdbc?useSSL=false&characterEncoding=utf8 ~~~ <br> 后面的两个参数表示不使用SSL加密,使用UTF-8作为字符编码(注意MySQL的UTF-8是`utf8`)。 要获取数据库连接,使用如下代码: ``` package day07; import java.sql.DriverManager; public class day01jdbc { public static void main(String args[]){ // JDBC连接的url,不同数据库有不同的格式 String JDBC_URL = "jdbc:mysql://localhost:3306/go_gin_test"; String JDBC_USER = "root"; String JDBC_PASSWORD = "12345"; // 获得连接 Connection conn = DriverManager.getConnection(JDBC_URL,JDBC_USER,JDBC_PASSWORD); // 访问数据库 // 关闭连接 conn.close(); } } ``` <br> <br> 核心代码是`DriverManager`提供的静态方法`getConnection()`。`DriverManager`会自动扫描classpath,找到所有的JDBC驱动,然后根据我们传入的URL自动挑选一个合适的驱动。 因为JDBC连接是一种昂贵的资源,所以使用后要及时释放。使用`try (resource)`来自动释放JDBC连接是一个好方法: ``` try (Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD)) { ... } ``` <br> <br> ## 二、JDBC中常用类和接口 连接到数据库(Connection)、建立操作指令(Statement)、执行查询指令(executeQuery)、获得查询结果(ResultSet)等。 ### 1、驱动程序管理类(DriverManager) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DriverManager类是JDBC的管理类,作用于用户和驱动程序之间。它跟踪在可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager类也处理诸如驱动程序登陆时间限制及登录和跟踪消息的显示事务。对于简单的应用程序,一般程序员需要在此类中直接使用唯一的方法时DriverManager.getConnection()。该方法将建立与数据库的链接。JDBC允许用户调用DriverManager的方法getDriver()、getDrivers()和registerDriver()及Driver的方法connect(). ### 2、声明类(Statement) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Statement对象用于将SQL语句发送到数据库中。实际上有三种Statement对象,它们都作为在给定链接上执行SQL语句的包容器:Statement、PreparedStatement(它从Statement继承而来)和CallableStatement(它从PreparedStatement继承而来)。它们都专用于发送特定类型的SQL语句: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)Statement对象用于执行不带参数的简单的SQL语句;Statement接口提供了执行语句和获取结果的基本方法。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)PerparedStatement对象用于执行带或不带IN参数的预编译SQL语句;PeraredStatement接口添加处理IN参数的方法; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)CallableStatement对象用于执行对数据库已存储过程的调用;CallableStatement添加处理OUT参数的方法。 #### Statement提供了许多方法,最常用的方法如下: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)execute()方法:运行语句,返回是否有结果集。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)executeQuery()方法:运行查询语句,返回ReaultSet对象。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)executeUpdata()方法:运行更新操作,返回更新的行数。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)addBatch()方法:增加批处理语句。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)executeBatch()方法:执行批处理语句。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (6)clearBatch()方法:清除批处理语句。 ### 3、数据库连接类 (Connection) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Connection对象代表与数据库的链接。连接过程包括所执行的SQL语句和在该连接上所返回的结果。一个应用程序可与单个数据库有一个或多个连接,或者可与很多数据库有连接。打开连接与数据库建立连接的标准方法是调用DriverManager.getConnection()方法。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url="jdbc:mysql://127.0.0.1:3306/imooc"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String user="root"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String password="tiger"; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DriverManager.getConnection(url,user,password); ### 4、结果集合类 (ResultSet) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ResultSet包含符合SQL语句中条件的所有行记录,并且它通过一套get方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next()方法用于移动到ResultSet中的下一行,使下一行成为当前行。 5、JDBC编程步骤 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (1)加载驱动程序:Class.forName(driverClass) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 加载mysql驱动:Class.forName("com.mysql.jdbc.Driver"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 加载oracle驱动:Class.forName("oracle.jdbc.driver.OracleDriver"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (2)获得数据库连接 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/imooc",user,password); DriverManager.gerConnection(URL,user,password); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (3)创建Statement对象:conn.createStatement(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (4)向数据库发送SQL命令 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (5)处理数据库的返回结果(ResultSet类) <br> **案例演示:** ``` package day07; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.sql.*; import java.util.Properties; import org.apache.log4j.Logger; public class day01jdbc { // MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL // static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; // static final String DB_URL = "jdbc:mysql://localhost:3306/go_gin_test"; // MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL /* * final:修饰的类不能被继承。 * static:修饰符能够与变量、方法一起使用,表示是“静态”的 * */ // static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver"; // static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/go_gin_test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC"; // 日志方法 private static Logger logger = Logger.getLogger(day01jdbc.class); // 配置文件封装方法 private static String LoadProperties(String jdbcPATH,String jdbcData) throws Exception { Properties properties = new Properties(); // Properties该类主要用于读取Java的配置文件, // FileInputStream流被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作如读取图片视频等 InputStream iStream = new FileInputStream(new File(jdbcPATH)); properties.load(iStream); // 使用Properties对象里的方法读取FileInputStream返回的字节流 /* * getProperty在此属性列表中搜索具有指定键的属性。如果在此属性列表中找不到该键,则会检查默认属性列表及其默认值(递归)。如果未找到该属性,则该方法返回默认值参数。 * */ // String key = properties.getProperty("jdbc.USER"); String key = properties.getProperty(jdbcData); return key; } public static void main(String[] args) throws Exception { //ClassNotFoundException 应用程序试图加载类时,找不到相应的类,抛出该异常。 String DB_URL = LoadProperties("src/day07/jdbcmysql.properties","jdbc.DB_URL"); String USER = LoadProperties("src/day07/jdbcmysql.properties","jdbc.USER"); String PASS = LoadProperties("src/day07/jdbcmysql.properties","jdbc.PASS"); String JDBC_DRIVER = LoadProperties("src/day07/jdbcmysql.properties","jdbc.JDBC_DRIVER"); Connection conn = null; Statement stmt = null; try { // 注册 JDBC 驱动 logger.info(Class.forName(JDBC_DRIVER)); // 打开链接 System.out.println("连接数据库..."); // DriverManager`提供的静态方法`getConnection()`自动扫描classpath,找到所有的JDBC驱动,然后根据我们传入的URL自动挑选一个合适的驱动。 conn = DriverManager.getConnection(DB_URL, USER, PASS); logger.info(conn); // 执行查询 System.out.println(" 实例化Statement对象..."); stmt = conn.createStatement(); logger.info(stmt); String sql; sql = "SELECT id, `name`, money FROM gin_user"; ResultSet rs = stmt.executeQuery(sql); // 展开结果集数据库 while (rs.next()) { // next 返回第一个元素 // 通过字段检索 int id = rs.getInt("id"); String name = rs.getString("name"); String money = rs.getString("money"); // 输出数据 System.out.print("ID: " + id); System.out.print(", NAME: " + name); System.out.print(", money: " + money); System.out.print("\n"); } // 完成后关闭 rs.close(); stmt.close(); conn.close(); } catch (SQLException se) { // 处理 JDBC 错误 logger.info(se); se.printStackTrace(); } catch (Exception e) { // 处理 Class.forName 错误 logger.info(e); e.printStackTrace(); } finally { // 关闭资源 try { if (stmt != null) stmt.close(); } catch (SQLException se2) { }// 什么都不做 try { if (conn != null) conn.close(); } catch (SQLException se) { se.printStackTrace(); } } System.out.println("Goodbye!"); } } ``` **运行结果:** ``` [INFO] 2021-02-12 17:15:11 method: day07.day01jdbc.main(day01jdbc.java:54)----class com.mysql.cj.jdbc.Driver 连接数据库... [INFO] 2021-02-12 17:15:11 method: day07.day01jdbc.main(day01jdbc.java:60)----com.mysql.cj.jdbc.ConnectionImpl@38082d64 实例化Statement对象... [INFO] 2021-02-12 17:15:11 method: day07.day01jdbc.main(day01jdbc.java:65)----com.mysql.cj.jdbc.StatementImpl@5d624da6 ID: 1, NAME: WW, money: 23492 ID: 2, NAME: 风清扬, money: 23021 ID: 3, NAME: 洪七公, money: 18000 ID: 4, NAME: 降龙十八掌, money: 8000 ID: 5, NAME: 张无忌, money: 6000 ID: 6, NAME: 张三丰, money: 13000 ID: 7, NAME: 杨过, money: 9210 ID: 8, NAME: 小龙女, money: 5000 ID: 9, NAME: 小龙女, money: 5200 ID: 10, NAME: WW, money: 3210 ID: 11, NAME: 马可波罗, money: 10100 ID: 12, NAME: 令狐冲, money: 2340 ID: 13, NAME: 东方不败, money: 7800 ID: 14, NAME: 独孤求败, money: 12380 ID: 15, NAME: 剑圣, money: 29380 ID: 16, NAME: taotaomao, money: 3400 ID: 17, NAME: meimeixin, money: 5400 ID: 18, NAME: kexinle, money: 6800 ID: 19, NAME: HdfFFs, money: 3452 ID: 20, NAME: PdSSc, money: 23410 ID: 21, NAME: asjkhd, money: 23121 Goodbye! ``` <br> <br> ## 数据类型 有的童鞋可能注意到了,使用JDBC的时候,我们需要在Java数据类型和SQL数据类型之间进行转换。JDBC在`java.sql.Types`定义了一组常量来表示如何映射SQL数据类型,但是平时我们使用的类型通常也就以下几种: | SQL数据类型 | Java数据类型 | | --- | --- | | BIT, BOOL | boolean | | INTEGER | int | | BIGINT | long | | REAL | float | | FLOAT, DOUBLE | double | | CHAR, VARCHAR | String | | DECIMAL | BigDecimal | | DATE | java.sql.Date, LocalDate | | TIME | java.sql.Time, LocalTime | 注意:只有最新的JDBC驱动才支持`LocalDate`和`LocalTime`。