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 表的数据

 String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false";
String username = "root";
String password = "123456"; Class.forName(driver); Connection conn = null;
Statement stmt = null;
ResultSet rs = null; try {
conn = DriverManager.getConnection(url, username, password); stmt = conn.createStatement();
rs = stmt.executeQuery("select id, username, role_id from t_user"); while (rs.next()) {
int id = rs.getInt(1);
String uname = rs.getString("username");
int roleId = rs.getInt(3);
System.out.println("用户信息: id=" + id + ", username=" + uname + ", role_id=" + roleId);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (conn != null)
conn.close();
if (stmt != null)
stmt.close();
if (rs != null)
rs.close();
} catch (SQLException e) {
}
}

代码解读

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 类

 public class DBUtil {

     private static String driver;
private static String url;
private static String username;
private static String password; private static Properties prop = new Properties(); static {
try {
prop.load(DBUtil.class.getClassLoader().getResourceAsStream(
"jdbc.properties")); driver = prop.getProperty("driver");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password"); Class.forName(driver); } catch (IOException e) {
throw new RuntimeException("加载JDBC配置失败", e);
} catch (ClassNotFoundException e) {
throw new RuntimeException("加载JDBC配置失败", e);
}
} public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
}

最后,编写 JdbcDemo2 测试类

 Connection conn = null;
Statement stmt = null;
ResultSet rs = null; try {
// 获取连接
conn = DBUtil.getConnection(); stmt = conn.createStatement();
// 执行查询并获取结果集
rs = stmt.executeQuery("select id, username, role_id from t_user"); // 遍历结果集
while (rs.next()) {
int id = rs.getInt(1);
String uname = rs.getString("username");
int roleId = rs.getInt(3);
System.out.println("用户信息: id=" + id + ", username=" + uname + ", role_id=" + roleId);
} } catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭连接,释放资源
// 略
}

项目结构如下:

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

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

 public class UserDao {

     public Map<String, Object> getUserInfoById(int id) throws SQLException {

         // 拼接sql字符串
String sql = "select id, username, role_id from t_user where id = "+ id; Connection conn = null;
Statement stmt = null;
ResultSet rs = null; try {
// 获取连接
conn = DBUtil.getConnection(); stmt = conn.createStatement();
// 执行查询并获取结果集
rs = stmt.executeQuery(sql); Map<String, Object> user = new HashMap<String, Object>(); // 遍历结果集,封装数据并返回
if (rs.next()) {
String uname = rs.getString("username");
int roleId = rs.getInt(3);
user.put("id", id);
user.put("username", uname);
user.put("role_id", roleId);
}
return user; } catch (SQLException e) {
// 可以把异常抛给业务层的调用者
throw e;
} finally {
// 关闭连接,释放资源
// 略
}
} public static void main(String[] args) {
UserDao uDao = new UserDao();
try {
Map<String, Object> user = uDao.getUserInfoById(1);
System.out.println(user);
} catch (SQLException e) {
e.printStackTrace();
}
}
}

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

6、代码

点击下载

JDBC第一个案例的更多相关文章

  1. 学习ExtjsForVs(第一个案例HelloWord)

    第一个案例-Hello Word 1.本次练习以ext-4.0.7为例,首先从网上下载ext包. 2.打开包后将里面的三个文件或文件夹拷贝到项目中. resource文件夹 bootstrap.js ...

  2. spring boot实战(第一篇)第一个案例

    版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[+]   spring boot实战(第一篇)第一个案例 前言 写在前面的话 一直想将spring boot相关内容写成一个系列的 ...

  3. (转)编写Spring的第一个案例并测试Spring的开发环境

    http://blog.csdn.net/yerenyuan_pku/article/details/52832145 Spring4.2.5的开发环境搭建好了之后,我们来编写Spring的第一个案例 ...

  4. javascript进阶教程第一章案例实战

    javascript进阶教程第一章案例实战 一.学习任务 通过几个案例练习回顾学过的知识 通过练习积累JS的使用技巧 二.实例 练习1:删除确认提示框 实例描述: 防止用户小心单击了“删除”按钮,在用 ...

  5. JDBC第一天连接池案例

    JDBC,JDBC的工具类JDBC 连接从连接池中拿: 创建连接池的语句: package day01; import java.sql.Connection; import java.sql.Dri ...

  6. Javaweb入门 JDBC第一天

    JDBC的定义和作用 DBC(Java DataBase Connectivity) Java数据库连接, 其实就是利用Java语言/程序连接并访问数据库的一门技术. 之前我们可以通过cmd或者nav ...

  7. 第91讲:Akka第一个案例动手实战架构设计

    我们来看一下Akka的一个简单的wordcount的案例架构设计 从图中我们可以看出,不同的行我们是交给不同的actor进行入理的,每行首先进行map操作,识别出每个单词,然后交给reduce步骤的a ...

  8. Hibernate—第一个案例

    百度百科上是这样写道的:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可 ...

  9. MyBatis第一个案例-----永远的HelloWorld 含所有代码

    1.创建表emp CREATE DATABASE mybatis; USE mybatis; CREATE TABLE emp( id INT(11) PRIMARY KEY AUTO_INCREME ...

随机推荐

  1. Cobaltstrike与Metasploit会话转换

    这里只做记录,不做详解 0x00 实验环境 被控制机:192.168.126.129 Metasploit:192.168.126.128 Cobaltstrike:182...* 0x01 CS会话 ...

  2. fluent计算输出时均值

    / ****************************************************************************** * Created on : 2017 ...

  3. Mybatis 面试题

    题目: 什么是Mybatis?  Mybatis27题 Mybaits的优点 Mybatis27题 MyBatis框架的缺点 Mybatis27题 MyBatis框架适用场合Mybatis27题 My ...

  4. vue+elementui搭建后台管理界面(6登录和菜单权限控制)

    不同的权限对应不同的路由(菜单),同时侧边栏也根据权限异步生成,实现登录和鉴权思路如下: 登录:点击登录,服务器验证通过后返回一个 token ,然后存到 cookie,再根据 token 拉取用户权 ...

  5. git,指南,操作

    助你开始使用 git 的简易指南,木有高深内容,;). Tweet 作者:罗杰·杜德勒 感谢:@tfnico, @fhd and Namics其他语言 english, deutsch, españo ...

  6. [转]Json字符串和map和HashMap之间的转换

    需要导入alibaba.fastJsonmaven中的依赖为 <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> ...

  7. String字符串与其他格式(int、boolean等八大数据类型)的相互转换

    1.(String 转 int)String str = "123"; int a = Integer.parseInt(str);(int 转 String)int a = 5; ...

  8. ingress nginx https配置

    3.https配置第一步:制作自签证书 [root@master demo]# openssl genrsa -out tls.key 2048 [root@master demo]# openssl ...

  9. jeff dean的主页

    https://ai.google/research/people/jeff/ 上面有他的很多论文和ppt 很不错 我于1999年中期加入Google,目前是研究小组的Google高级研究员,负责Go ...

  10. sass、less和stylus 相同与不同

    sass.less和stylus的安装使用和入门实践 https://www.jianshu.com/p/1eaf366814e2 stylus 基础教程 https://blog.csdn.net/ ...