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 表的数据
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 配置文件,主要配置 driver、url、username、password 等连接参数
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第一个案例的更多相关文章
- 学习ExtjsForVs(第一个案例HelloWord)
第一个案例-Hello Word 1.本次练习以ext-4.0.7为例,首先从网上下载ext包. 2.打开包后将里面的三个文件或文件夹拷贝到项目中. resource文件夹 bootstrap.js ...
- spring boot实战(第一篇)第一个案例
版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] spring boot实战(第一篇)第一个案例 前言 写在前面的话 一直想将spring boot相关内容写成一个系列的 ...
- (转)编写Spring的第一个案例并测试Spring的开发环境
http://blog.csdn.net/yerenyuan_pku/article/details/52832145 Spring4.2.5的开发环境搭建好了之后,我们来编写Spring的第一个案例 ...
- javascript进阶教程第一章案例实战
javascript进阶教程第一章案例实战 一.学习任务 通过几个案例练习回顾学过的知识 通过练习积累JS的使用技巧 二.实例 练习1:删除确认提示框 实例描述: 防止用户小心单击了“删除”按钮,在用 ...
- JDBC第一天连接池案例
JDBC,JDBC的工具类JDBC 连接从连接池中拿: 创建连接池的语句: package day01; import java.sql.Connection; import java.sql.Dri ...
- Javaweb入门 JDBC第一天
JDBC的定义和作用 DBC(Java DataBase Connectivity) Java数据库连接, 其实就是利用Java语言/程序连接并访问数据库的一门技术. 之前我们可以通过cmd或者nav ...
- 第91讲:Akka第一个案例动手实战架构设计
我们来看一下Akka的一个简单的wordcount的案例架构设计 从图中我们可以看出,不同的行我们是交给不同的actor进行入理的,每行首先进行map操作,识别出每个单词,然后交给reduce步骤的a ...
- Hibernate—第一个案例
百度百科上是这样写道的:Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可 ...
- MyBatis第一个案例-----永远的HelloWorld 含所有代码
1.创建表emp CREATE DATABASE mybatis; USE mybatis; CREATE TABLE emp( id INT(11) PRIMARY KEY AUTO_INCREME ...
随机推荐
- 关于python的深拷贝和浅拷贝
写类函数的时候出了一个错,原代码写在这里: def Update(self, wm, vm, ts, pos, vn, att): # 上一时刻位置,速度 pos_pre = pos self.pos ...
- 思科 DHCP服务器配置及DHCP中继
思路: 1.配置 DHCP 客户端 确保每个 PC 为 自动获取IP地址的方式: 2.配置 SW1 # 创建 VLAN 10 , 20 # 将相关的端口,放入到对应的 VLAN : # 配置交换机之间 ...
- [Beta]第九次 Scrum Meeting
[Beta]第九次 Scrum Meeting 写在前面 会议时间 会议时长 会议地点 2019/5/19 21:20 20min 大运村公寓6F寝室 附Github仓库:WEDO 例会照片 (一人回 ...
- 剑指offer:链表中环的入口结点
题目描述: 给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. 思路分析: 这道题首先需要判断链表是否存在环,很快就能想到用快慢指针来判断. 由于快慢指针的相遇位置并不一定为链 ...
- 定制比特币btc地址address
https://99bitcoins.com/how-to-get-a-custom-bitcoin-address/ https://en.bitcoin.it/wiki/Vanitygen htt ...
- 【转】vue中样式被覆盖的问题,vue中的style不生效
转载:http://www.cnblogs.com/shangjun6/p/11416054.html 在我们引入外部的样式时,发现自己无论如何都改不了外部的样式,自己的样式老被覆盖,究其原因还是我们 ...
- mysql 5.6配置
简洁版: [client] port = 3306 socket = /weyeedata/mysql/run/mysql.sock [mysqld] innodb_buffer_pool_size ...
- Intellij idea 告警:URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs)
URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs) 一.快捷键方式 鼠标移动到出错的的地方 ...
- (九)Knockout 进一步技术
加载和保存 JSON 数据 Knockout允许您实现复杂的客户端交互,但是几乎所有web应用程序还需要与服务器交换数据,或者至少要序列化数据以供本地存储.交换或存储数据最方便的方式是JSON格式-- ...
- openresty开发系列33--openresty执行流程之3重写rewrite和重定向
openresty开发系列33--openresty执行流程之3重写rewrite和重定向 重写rewrite阶段 1)重定向2)内部,伪静态 先介绍一下if,rewrite指令 一)if指令语法:i ...