博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
厚积薄发系列之JDBC详解
阅读量:5033 次
发布时间:2019-06-12

本文共 12256 字,大约阅读时间需要 40 分钟。

创建一个以JDBC链接数据库的程序,包含七个步骤

 

1.加载JDBC驱动

    • 加载要连接的数据库的驱动到JVM
    • 如何加载?forName(数据库驱动)
    • MySQL:Class.forName("com.mysql.jdbc.Driver");
    • Oracle10g:Class.forName("oracle.jdbc.driver.OracleDriver");
    • SQLServer2005:Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
    • 1         //1.加载驱动程序 mysql为例子2         try {3             Class.forName("com.mysql.jdbc.Driver");4         } catch (ClassNotFoundException e) {5             // TODO Auto-generated catch block6             e.printStackTrace();7             System.out.println("加载驱动失败");8         }

2.提供JDBC连接的URL

    • 连接URL定义了连接数据库时的协议,子协议,数据源标识
    • 根据不同的数据库产品不同连接的URL不同
      • Oracle10g:jdbc:oracle:thin:@主机名:端口:数据库SID
      • MySQL5:jdbc:mysql://主机名:端口/数据库名
      • SQLServer2005:jdbc:sqlserver://主机名:端口:DatabaseName=库名
    • 1     /**2      * 访问数据库的地址3      */4     private final String URL = "jdbc:mysql://localhost:3306/test";

3.创建数据库的链接

    • 连接数据库就要向java.sqlDriverManager请求过的Connection对象,一个Connection就代表一个数据库连接
    • 在连接的时候需要传入数据库的账户和密码
    • 1 Connection connection =  DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");

4.创建一个Statement

    • 获得数据库连接后,要想执行sql语句,必须获得java.sql.Statement实例,Statement实例分为三种
      • 执行静态的sql语句.通过Statement实例实现
      • 执行动态的sql语句.通过PreparedStatement实例实现
      • 执行数据库存储过程.通常通过CallableStatement实例实现
    • 1             //执行静态的sql2             Statement statement = connection.createStatement();3             ResultSet resultSet = statement.executeQuery("select * from sys_user");4             System.out.println(resultSet.toString());5             6             //执行动态的sql  采用预加载的方式 可防止sql注入7             PreparedStatement prepareStatement = connection.prepareStatement("select * from sys_user");

       

5.执行sql语句

  • Statement提供了三种执行查询
    • ResultSet executeQuery(String sql);   执行查询数据库的sql语句,返回一个结果集(ResultSet)对象
    • int executeUpdate(String sql);  执行INSERT,UPDATE或者DELETE语句以及SQL DDL语句,返回受影响行数
    • execute(String sql); 用于返回多个结果集,多个更新计数或者二者组合的语句
    • 1             //执行查询2             ResultSet resultSet = statement.executeQuery("select * from sys_user");3             //执行insert update delete 4             statement.executeUpdate("INSERT INTO sys_user VALUES(5,'lisi','123','李四');");

       

6.处理结果

  • 处理结果有两种情况
    • 返回本次操作的记录数 在执行executeUpdate();方法的时候会返回受影响的行数
    • 返回ResultSet对象  在执行executeQuery();方法的时候会返回对象 
  • ResultSet对象中包含SQL查询中出的所有行,通过get方法可以获取每行的数据
  • 1             //执行查询2             ResultSet resultSet = statement.executeQuery("select * from sys_user");3             while(resultSet.next()) {4                 System.out.println(resultSet.getInt("uid"));5                 System.out.println(resultSet.getString("username"));6                 System.out.println(resultSet.getString("password"));7                 System.out.println(resultSet.getString("nickname"));8             }

     

7.关闭JDBC对象

  • 在使用完毕后需要关闭三个对象,关闭结果集(resultSet),关闭声明(Statement),关闭数据库连接(Connection)
  • 1             if (resultSet != null) { // 关闭记录集2                 resultSet.close();3             }4             if (statement != null) { // 关闭声明5                 statement.close();6             }7             if (connection != null) { // 关闭连接对象8                 connection.close();9             }

     

我们可以把经常使用的方法封装成一个工具类,我们一般成为jdbcUtils,下面代码时从CSDN获取,大家可以自己借鉴修改,我就不再重复打出来了

1 package com.jdbc.dbutils;    2     3 import java.sql.Connection;    4 import java.sql.DriverManager;    5 import java.sql.PreparedStatement;    6 import java.sql.ResultSet;    7 import java.sql.ResultSetMetaData;    8 import java.sql.SQLException;    9 import java.util.ArrayList;   10 import java.util.HashMap;   11 import java.util.List;   12 import java.util.Map;   13    14 public class JdbcUtils {   15     /**  16      * 数据库的用户名  17      */   18     private final String USER = "root";   19     /**  20      * 数据库的密码  21      */   22     private final String PASSWORD = "123456";   23     /**  24      * 数据库的驱动信息  25      */   26     private final String DRIVER = "com.mysql.jdbc.Driver";   27     /**  28      * 访问数据库的地址  29      */   30     private final String URL = "jdbc:mysql://localhost:3306/test";   31     /**  32      * 数据库的连接  33      */   34     Connection connection;   35     /**  36      * sql语句的执行对象  37      */   38     PreparedStatement preparedStatement;   39     /**  40      * 查询返回的结果集合  41      */   42     ResultSet resultSet;   43    44     public JdbcUtils() {   45         try {   46             Class.forName(DRIVER);   47             System.out.println("注册驱动成功");   48         } catch (ClassNotFoundException e) {   49             e.printStackTrace();   50         }   51     }   52    53     /**  54      * 连接数据库  55      *   56      * @return 数据库的连接对象  57      */   58     public Connection getConnection() {   59         try {   60             connection = DriverManager.getConnection(URL, USER, PASSWORD);   61         } catch (SQLException e) {   62             e.printStackTrace();   63         }   64         return connection;   65     }   66    67     /**  68      * 完成对数据库的表的添加删除和修改的操作  69      *   70      * @param sql  71      * @param params  72      * @return  73      * @throws SQLException  74      */   75     public boolean updateByPrepareStatement(String sql, List params)   76             throws SQLException {   77         boolean flag = false;   78         int result = -1;// 表示当用户执行添加删除和修改的时候所影响数据库的行数   79         // 创建一个 PreparedStatement 对象来将参数化的 sql 语句发送到数据库。   80         preparedStatement = connection.prepareStatement(sql);   81         int index = 1;   82         if (params != null && !params.isEmpty()) {   83             for (Object object : params) {   84                 // 使用给定对象设置指定参数的值。index从1开始   85                 preparedStatement.setObject(index++, object);   86             }   87         }   88         // 在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言语句,比如   89         // INSERT、UPDATE 或 DELETE 语句   90         result = preparedStatement.executeUpdate();   91         flag = result > 0 ? true : false;   92         return flag;   93    94     }   95    96     /**  97      * 查询返回单条记录  98      *   99      * @param sql 100      * @param params 101      * @return 102      * @throws SQLException 103      */  104     public Map
findSimpleResult(String sql, List
params) 105 throws SQLException { 106 Map
map = new HashMap
(); 107 int index = 1; 108 // 创建一个 PreparedStatement 对象来将参数化的 sql 语句发送到数据库。 109 preparedStatement = connection.prepareStatement(sql); 110 if (params != null && !params.isEmpty()) { 111 for (Object object : params) { 112 // 使用给定对象设置指定参数的值。index从1开始 113 preparedStatement.setObject(index++, object); 114 } 115 } 116 // 在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。 117 resultSet = preparedStatement.executeQuery(); 118 // 获取此 ResultSet 对象的列的编号、类型和属性。 119 ResultSetMetaData metaData = resultSet.getMetaData(); 120 int col_len = metaData.getColumnCount(); 121 while (resultSet.next()) { 122 for (int i = 0; i < col_len; i++) { 123 // sql数据库列的下标是从1开始的 124 String col_name = metaData.getColumnName(i + 1); 125 Object col_value = resultSet.getObject(col_name); 126 if (col_value == null) { 127 col_value = ""; 128 } 129 map.put(col_name, col_value); 130 } 131 } 132 133 return map; 134 } 135 136 public List
> findMoreResult(String sql, 137 List
params) throws SQLException { 138 List
> list = new ArrayList
>(); 139 int index = 1; 140 // 创建一个 PreparedStatement 对象来将参数化的 sql 语句发送到数据库。 141 preparedStatement = connection.prepareStatement(sql); 142 if (params != null && !params.isEmpty()) { 143 for (Object object : params) { 144 // 使用给定对象设置指定参数的值。index从1开始 145 preparedStatement.setObject(index++, object); 146 } 147 } 148 // 在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。 149 resultSet = preparedStatement.executeQuery(); 150 // 获取此 ResultSet 对象的列的编号、类型和属性。 151 ResultSetMetaData metaData = resultSet.getMetaData(); 152 int col_len = metaData.getColumnCount(); 153 while (resultSet.next()) { 154 Map
map = new HashMap
(); 155 for (int i = 0; i < col_len; i++) { 156 // sql数据库列的下标是从1开始的 157 String col_name = metaData.getColumnName(i + 1); 158 Object col_value = resultSet.getObject(col_name); 159 if (col_value == null) { 160 col_value = ""; 161 } 162 map.put(col_name, col_value); 163 } 164 list.add(map); 165 } 166 return list; 167 } 168 169 /** 170 * 关闭数据库 171 * 172 * @throws SQLException 173 */ 174 public void releaseConn() throws SQLException { 175 if (resultSet != null) { 176 resultSet.close(); 177 } 178 179 if (preparedStatement != null) { 180 preparedStatement.close(); 181 } 182 if (connection != null) { 183 connection.close(); 184 } 185 } 186 187 static JdbcUtils jdbcUtils; 188 189 public static void main(String[] args) throws SQLException { 190 jdbcUtils = new JdbcUtils(); 191 jdbcUtils.getConnection(); 192 // insert(); 193 // update(); 194 // query(); 195 Morequery(); 196 } 197 198 private static void query() throws SQLException { 199 String sql = "select * from userinfo where pwd = ? "; 200 List
params = new ArrayList(); 201 params.add("123"); 202 Map
map = jdbcUtils.findSimpleResult(sql, params); 203 System.out.println(map); 204 } 205 206 private static void Morequery() throws SQLException { 207 String sql = "select * from userinfo "; 208 List
> map = jdbcUtils.findMoreResult(sql, null); 209 System.out.println(map); 210 } 211 212 /** 213 * 更新数据库内容 214 * 215 * @throws SQLException 216 */ 217 private static void update() throws SQLException { 218 String sql = "update userinfo set username =? where id=2"; 219 List
params = new ArrayList(); 220 params.add("liumr"); 221 jdbcUtils.updateByPrepareStatement(sql, params); 222 } 223 224 /** 225 * 增加数据 226 * 227 * @throws SQLException 228 */ 229 private static void insert() throws SQLException { 230 String sql = "insert userinfo (username,pwd) values (?,?)"; 231 List params = new ArrayList(); 232 params.add("liugx"); 233 params.add("456"); 234 jdbcUtils.updateByPrepareStatement(sql, params); 235 236 } 237 238 }
View Code

 

数据库连接池技术

 

  • 由于我们要对数据库频繁地进行操作,每进行一次连接操作就要获取一个conntection连接,每次使用完毕后要全部关闭资源,这样的话我们可以使用数据库连接池技术
  • 优点:
    • 资源重用:避免重复创建,释放连接,大量节约性能开销
    • 更快的响应:在连接池初始化的过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。
    • 新的资源分配手段: 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源
    • 统一的连接管理,避免数据库连接泄露:  在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
  • 创建的数据库连接池
    • DBCP:由于性能问题,已经很少使用了
    • C3P0:目前在很多项目中都在使用
    • Druid(阿里巴巴):阿里巴巴开源的一个数据库连接池
  •  下面我们示范常用的C3p0的使用
    • 导入jar包c3p0-0.9.1.2.jar
    • 在项目src目录下新建c3p0.properties
      • 文件内容(当然还有很多其他配置,下面最简单配置)
      • c3p0.driverClass=com.mysql.jdbc.Driverc3p0.jdbcUrl=jdbc:mysql://localhost:3306/testc3p0.user=rootc3p0.password=root

         

    • 在与数据库交互时
    • 1 //创建一个数据库连接池ComboPooledDataSource ds = new ComboPooledDataSource();2 //创建QueryRunner接口3 QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());4 //通过接口可以执行查询或者更新,修改操作5   qr.update(sql); //返回受影响的行数6   qr.query(sql, null); //返回各种类型

       

    •  关于QueryRunner的query方法其实功能是很强大的,可以根据查询的内容自动封装各种类型
      • 封装入一个javaBean中
      • 1 public Category getById(String cid) throws Exception {2         QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());3         String sql = "select * from category where cid = ?";4         return qr.query(sql, new BeanHandler<>(Category.class), cid);5     }

         

      • 封装成一个可以指定类型的list集合
      • 1 public List
        findAll() throws Exception {2 QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());3 String sql = "select * from category";4 List
        list = qr.query(sql, new BeanListHandler<>(Category.class));5 return list;6 }

         

      • 返回单条数据
      • 1     /** 2      * 查询数据总条数 3      */ 4     @Override 5     public Integer getTotalSize() throws Exception { 6         // 创建查询接口 7         QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource()); 8         String sql = "select count(*) from links"; 9         return ((Long) qr.query(sql, new ScalarHandler())).intValue();10     }

         

    • C3p0是在项目中是很详细的,详细的学习该请大家参考正式的文档

转载于:https://www.cnblogs.com/jimisun/p/7812756.html

你可能感兴趣的文章
ubuntu设计文件权限
查看>>
http://lorempixel.com/ 可以快速产生假图
查看>>
Centos7下载和安装教程
查看>>
无谓的通宵加班之后的思索
查看>>
S1的小成果:MyKTV系统
查看>>
从setting文件导包
查看>>
编写一个函数isMerge,判断一个字符串str是否可以由其他两个字符串part1和part2“组合”而成...
查看>>
Github 开源:使用控制器操作 WinForm/WPF 控件( Sheng.Winform.Controls.Controller)
查看>>
PMD使用提醒
查看>>
Codeforces 887D Ratings and Reality Shows
查看>>
论文《A Generative Entity-Mention Model for Linking Entities with Knowledge Base》
查看>>
Linux记录-salt分析
查看>>
Android Studio默认快捷键
查看>>
函数式编程与参数
查看>>
SSAS使用MDX生成脱机的多维数据集CUB文件
查看>>
HDU 2191 【多重背包】
查看>>
51nod 1433 0和5【数论/九余定理】
查看>>
【AHOI2013复仇】从一道题来看DFS及其优化的一般步骤和数组分层问题【转】
查看>>
less 分页显示文件内容
查看>>
如何对数据按某列进行分层处理
查看>>