zoukankan      html  css  js  c++  java
  • JDBC第一个案例

    1、概述

    JDBC(Java DataBase Connectivity) 是 Java 提供的用于执行 SQL 语句一套 API,可以为多种关系型数据库提供统一访问,由一套用 Java 语言编写的类和接口组成。

    有了这套接口之后,开发者就不必为每一种数据库编写不同的访问逻辑,只需要在项目中加入数据库厂商提供的 JDBC 驱动,然后面向这套 Java API 接口开发自己的程序即可。

    也就是说,在没有使用某个数据库特有语法、函数的情况下,开发者只要替换数据库驱动包、修改连接配置文件即可在应用层实现数据库的替换。

    这就是面向接口编程的优势所在。

    JDBC最核心的几个接口

    Connection 与特定数据库的连接,SQL语句在这个连接上执行并返回结果
    Statement 静态SQL语句对象
    PreparedStatement 预编译的SQL语句对象
    ResultSet 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成

    2、第一个 demo

    环境:JDK 1.6 + mysql 5.5

    首先创建一个 java 项目 jdbc_demo

    导入 mysql-connector-java-5.1.26-bin.jar,这个数据库驱动可以到 http://mvnrepository.com 下载,关于 eclipse 的导包可以参考 http://5ijy01.duapp.com/it/java/java01046.html#f2-7

    创建 package 和测试类,如下:

     编写代码连接本地 MySQL 查询 test 下 t_user 表的数据

     1 String driver = "com.mysql.jdbc.Driver";
     2 String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false";
     3 String username = "root";
     4 String password = "123456";
     5 
     6 Class.forName(driver);
     7 
     8 Connection conn = null;
     9 Statement stmt = null;
    10 ResultSet rs = null;
    11 
    12 try {
    13     conn = DriverManager.getConnection(url, username, password);
    14 
    15     stmt = conn.createStatement();
    16     rs = stmt.executeQuery("select id, username, role_id from t_user");
    17 
    18     while (rs.next()) {
    19         int id = rs.getInt(1);
    20         String uname = rs.getString("username");
    21         int roleId = rs.getInt(3);
    22         System.out.println("用户信息: id=" + id + ", username=" + uname + ", role_id=" + roleId);
    23     }
    24 } catch (SQLException e) {
    25     e.printStackTrace();
    26 } finally {
    27     try {
    28         if (conn != null)
    29             conn.close();
    30         if (stmt != null)
    31             stmt.close();
    32         if (rs != null)
    33             rs.close();
    34     } catch (SQLException e) {
    35     }
    36 }

    代码解读

    url 是数据库连接地址,它告诉数据库驱动数据库服务器的 IP地址、服务监听端口、使用的数据库以及连接配置参数,这个 url 的配置方式通常在数据库文档中可以找到

    Class.forName(driver) 这行代码的作用是加载数据库驱动类

    下面的代码就比较简单了:使用 DriverManager 获取一个数据库连接 Connection 对象、从连接创建 Statement 对象,然后执行语句获取 ResultSet 结果集,最后迭代结果集获取数据

    需要注意的是:我们使用 finally 代码块关闭数据库连接资源,因为不论 try 代码块是否捕获到异常, finally 代码块都会执行

    3、API

    Connection 的核心方法
    void close() 释放Connection对象的数据库和JDBC资源
    void commit() 提交所有更改,并释放Connection对象当前持有的所有数据库锁
    Statement createStatement() 创建一个Statement对象来将SQL语句发送到数据库
    PreparedStatement prepareStatement(String sql) 创建一个PreparedStatement对象来将参数化的SQL语句发送到数据库
    void rollback() 取消当前事务中进行的所有更改,并释放Connection对象当前持有的所有数据库锁
    void setAutoCommit(boolean autoCommit) 设置是否自动提交
    void setReadOnly(boolean readOnly) 设置为只读模式,作为驱动程序启用数据库优化的提示
    void setTransactionIsolation(int level) 试图将此Connection对象的事务隔离级别更改为给定的级别
    Statement 的核心方法
    void addBatch(String sql) 将给定的SQL命令添加到Statement对象的当前命令列表中
    void close() 释放Statement对象的数据库和JDBC资源,而不是等待该对象自动关闭时发生此操作
    boolean execute(String sql) 执行给定的SQL语句,该语句可能返回多个结果
    int[] executeBatch() 将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组
    ResultSet executeQuery(String sql) 执行给定的SQL语句,该语句返回单个ResultSet对象
    int executeUpdate(String sql) 执行给定SQL语句,该语句可能为INSERT、UPDATE或DELETE语句,或者不返回任何内容的SQL语句(如DDL语句)
    ResultSet 的核心方法
    void close() 释放ResultSet对象的数据库和JDBC资源
    BigDecimal getBigDecimal(int columnIndex) 以具有全精度的java.math.BigDecimal的形式获取此ResultSet对象的当前行中指定列的值
    BigDecimal getBigDecimal(String columnLabel) 以具有全精度的java.math.BigDecimal的形式获取此ResultSet对象的当前行中指定列的值
    Date getDate(int columnIndex) 以java.sql.Date对象的形式获取此ResultSet对象的当前行中指定列的值
    Date getDate(String columnLabel) 以java.sql.Date对象的形式获取此ResultSet对象的当前行中指定列的值
    double getDouble(int columnIndex) 以double的形式获取此ResultSet对象的当前行中指定列的值
    double getDouble(String columnLabel) 以double的形式获取此ResultSet对象的当前行中指定列的值
    int getInt(int columnIndex) 以int的形式获取此ResultSet对象的当前行中指定列的值
    int getInt(String columnLabel) 以int的形式获取此ResultSet对象的当前行中指定列的值
    ResultSetMetaData getMetaData() 获取此ResultSet对象的列的编号、类型和属性
    Object getObject(int columnIndex) 以Object的形式获取此ResultSet对象的当前行中指定列的值
    Object getObject(String columnLabel) 以Object的形式获取此ResultSet对象的当前行中指定列的值
    String getString(int columnIndex) 以String的形式获取此ResultSet对象的当前行中指定列的值
    String getString(String columnLabel) 以String的形式获取此ResultSet对象的当前行中指定列的值
    Timestamp getTimestamp(int columnIndex) 以java.sql.Timestamp对象的形式获取此ResultSet对象的当前行中指定列的值
    Timestamp getTimestamp(String columnLabel) 以java.sql.Timestamp对象的形式获取此ResultSet对象的当前行中指定列的值
    boolean next() 将光标从当前位置向前移一行

    4、编写 DBUtil 连接工具类

    在一个项目里面,会有很多的业务需要访问数据库,如果每次都使用上面的方式获取连接,代码写起来会很麻烦,而且不便于维护

    所以我们可以把加载驱动、获取连接的代码提取出来,单独封装成一个工具类,对外只提供一个 getConnection() 的方法来获取连接

    jdbc.properties 配置文件

    首先,在 src 下添加 jdbc.properties 配置文件,主要配置 driverurlusernamepassword 等连接参数

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false
    username=root
    password=123456

    然后,编写 DBUtil 类

     1 public class DBUtil {
     2 
     3     private static String driver;
     4     private static String url;
     5     private static String username;
     6     private static String password;
     7 
     8     private static Properties prop = new Properties();
     9 
    10     static {
    11         try {
    12             prop.load(DBUtil.class.getClassLoader().getResourceAsStream(
    13                     "jdbc.properties"));
    14 
    15             driver = prop.getProperty("driver");
    16             url = prop.getProperty("url");
    17             username = prop.getProperty("username");
    18             password = prop.getProperty("password");
    19 
    20             Class.forName(driver);
    21 
    22         } catch (IOException e) {
    23             throw new RuntimeException("加载JDBC配置失败", e);
    24         } catch (ClassNotFoundException e) {
    25             throw new RuntimeException("加载JDBC配置失败", e);
    26         }
    27     }
    28 
    29     public static Connection getConnection() throws SQLException {
    30         return DriverManager.getConnection(url, username, password);
    31     }
    32 }

    最后,编写 JdbcDemo2 测试类

     1 Connection conn = null;
     2 Statement stmt = null;
     3 ResultSet rs = null;
     4 
     5 try {
     6     // 获取连接
     7     conn = DBUtil.getConnection();
     8 
     9     stmt = conn.createStatement();
    10     // 执行查询并获取结果集
    11     rs = stmt.executeQuery("select id, username, role_id from t_user");
    12 
    13     // 遍历结果集
    14     while (rs.next()) {
    15         int id = rs.getInt(1);
    16         String uname = rs.getString("username");
    17         int roleId = rs.getInt(3);
    18         System.out.println("用户信息: id=" + id + ", username=" + uname + ", role_id=" + roleId);
    19     }
    20 
    21 } catch (SQLException e) {
    22     e.printStackTrace();
    23 } finally {
    24     // 关闭连接,释放资源
    25     //
    26 }

    项目结构如下:

    5、字符串拼接方式执行动态查询

    创建一个 UserDao 类,用上面的方式编写一个使用id查询用户的方法

     1 public class UserDao {
     2 
     3     public Map<String, Object> getUserInfoById(int id) throws SQLException {
     4 
     5         // 拼接sql字符串
     6         String sql = "select id, username, role_id from t_user where id = "+ id;
     7 
     8         Connection conn = null;
     9         Statement stmt = null;
    10         ResultSet rs = null;
    11 
    12         try {
    13             // 获取连接
    14             conn = DBUtil.getConnection();
    15 
    16             stmt = conn.createStatement();
    17             // 执行查询并获取结果集
    18             rs = stmt.executeQuery(sql);
    19 
    20             Map<String, Object> user = new HashMap<String, Object>();
    21 
    22             // 遍历结果集,封装数据并返回
    23             if (rs.next()) {
    24                 String uname = rs.getString("username");
    25                 int roleId = rs.getInt(3);
    26                 user.put("id", id);
    27                 user.put("username", uname);
    28                 user.put("role_id", roleId);
    29             }
    30             return user;
    31 
    32         } catch (SQLException e) {
    33             // 可以把异常抛给业务层的调用者
    34             throw e;
    35         } finally {
    36             // 关闭连接,释放资源
    37             //
    38         }
    39     }
    40 
    41     public static void main(String[] args) {
    42         UserDao uDao = new UserDao();
    43         try {
    44             Map<String, Object> user = uDao.getUserInfoById(1);
    45             System.out.println(user);
    46         } catch (SQLException e) {
    47             e.printStackTrace();
    48         }
    49     }
    50 }

    这个方法很简单,也符合我们正常的编码习惯,但是 PreparedStatement 相比,执行效率较低,而且也有 SQL 的风险

    6、代码

    点击下载

  • 相关阅读:
    从零一起学Spring Boot之LayIM项目长成记(五)websocket
    从斐波那契数列看递归和尾递归
    通讯框架 t-io 学习——websocket 部分源码解析
    通讯框架 t-io 学习——给初学者的Demo:ShowCase设计分析
    从零一起学Spring Boot之LayIM项目长成记(四) Spring Boot JPA 深入了解
    从零一起学Spring Boot之LayIM项目长成记(三) 数据库的简单设计和JPA的简单使用。
    从零一起学Spring Boot之LayIM项目长成记(二) LayIM初体验
    从零一起学Spring Boot之LayIM项目长成记(一) 初见 Spring Boot
    初始Turtle
    python介绍
  • 原文地址:https://www.cnblogs.com/xugf/p/9219703.html
Copyright © 2011-2022 走看看