厚积薄发系列之JDBC详解
创建一个以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.加载驱动程序 mysql为例子
- try {
- Class.forName("com.mysql.jdbc.Driver");
- } catch (ClassNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- System.out.println("加载驱动失败");
- }
- //1.加载驱动程序 mysql为例子
2.提供JDBC连接的URL
- 连接URL定义了连接数据库时的协议,子协议,数据源标识
- 根据不同的数据库产品不同连接的URL不同
- Oracle10g:jdbc:oracle:thin:@主机名:端口:数据库SID
- MySQL5:jdbc:mysql://主机名:端口/数据库名
- SQLServer2005:jdbc:sqlserver://主机名:端口:DatabaseName=库名
- /**
- * 访问数据库的地址
- */
- private final String URL = "jdbc:mysql://localhost:3306/test";
- /**
3.创建数据库的链接
- 连接数据库就要向java.sqlDriverManager请求过的Connection对象,一个Connection就代表一个数据库连接
- 在连接的时候需要传入数据库的账户和密码
- Connection connection =
DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "root");
- Connection connection =
4.创建一个Statement
- 获得数据库连接后,要想执行sql语句,必须获得java.sql.Statement实例,Statement实例分为三种
- 执行静态的sql语句.通过Statement实例实现
- 执行动态的sql语句.通过PreparedStatement实例实现
- 执行数据库存储过程.通常通过CallableStatement实例实现
- 获得数据库连接后,要想执行sql语句,必须获得java.sql.Statement实例,Statement实例分为三种
- //执行静态的sql
- Statement statement = connection.createStatement();
- ResultSet resultSet = statement.executeQuery("select * from sys_user");
- System.out.println(resultSet.toString());
- //执行动态的sql 采用预加载的方式 可防止sql注入
- PreparedStatement prepareStatement = connection.prepareStatement("select * from sys_user");
- //执行静态的sql
5.执行sql语句
- Statement提供了三种执行查询
- ResultSet executeQuery(String sql); 执行查询数据库的sql语句,返回一个结果集(ResultSet)对象
- int executeUpdate(String sql); 执行INSERT,UPDATE或者DELETE语句以及SQL DDL语句,返回受影响行数
- execute(String sql); 用于返回多个结果集,多个更新计数或者二者组合的语句
- //执行查询
- ResultSet resultSet = statement.executeQuery("select * from sys_user");
- //执行insert update delete
- statement.executeUpdate("INSERT INTO sys_user VALUES(5,'lisi','123','李四');");
- //执行查询
6.处理结果
- 处理结果有两种情况
- 返回本次操作的记录数 在执行executeUpdate();方法的时候会返回受影响的行数
- 返回ResultSet对象 在执行executeQuery();方法的时候会返回对象
- ResultSet对象中包含SQL查询中出的所有行,通过get方法可以获取每行的数据
- //执行查询
- ResultSet resultSet = statement.executeQuery("select * from sys_user");
- while(resultSet.next()) {
- System.out.println(resultSet.getInt("uid"));
- System.out.println(resultSet.getString("username"));
- System.out.println(resultSet.getString("password"));
- System.out.println(resultSet.getString("nickname"));
- }
- //执行查询
7.关闭JDBC对象
- 在使用完毕后需要关闭三个对象,关闭结果集(resultSet),关闭声明(Statement),关闭数据库连接(Connection)
- if (resultSet != null) { // 关闭记录集
- resultSet.close();
- }
- if (statement != null) { // 关闭声明
- statement.close();
- }
- if (connection != null) { // 关闭连接对象
- connection.close();
- }
- if (resultSet != null) { // 关闭记录集
我们可以把经常使用的方法封装成一个工具类,我们一般成为jdbcUtils,下面代码时从CSDNhttp://blog.csdn.net/harryweasley/article/details/45689023获取,大家可以自己借鉴修改,我就不再重复打出来了
- package com.jdbc.dbutils;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import java.sql.ResultSetMetaData;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- public class JdbcUtils {
- /**
- * 数据库的用户名
- */
- private final String USER = "root";
- /**
- * 数据库的密码
- */
- private final String PASSWORD = "123456";
- /**
- * 数据库的驱动信息
- */
- private final String DRIVER = "com.mysql.jdbc.Driver";
- /**
- * 访问数据库的地址
- */
- private final String URL = "jdbc:mysql://localhost:3306/test";
- /**
- * 数据库的连接
- */
- Connection connection;
- /**
- * sql语句的执行对象
- */
- PreparedStatement preparedStatement;
- /**
- * 查询返回的结果集合
- */
- ResultSet resultSet;
- public JdbcUtils() {
- try {
- Class.forName(DRIVER);
- System.out.println("注册驱动成功");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- /**
- * 连接数据库
- *
- * @return 数据库的连接对象
- */
- public Connection getConnection() {
- try {
- connection = DriverManager.getConnection(URL, USER, PASSWORD);
- } catch (SQLException e) {
- e.printStackTrace();
- }
- return connection;
- }
- /**
- * 完成对数据库的表的添加删除和修改的操作
- *
- * @param sql
- * @param params
- * @return
- * @throws SQLException
- */
- public boolean updateByPrepareStatement(String sql, List<Object> params)
- throws SQLException {
- boolean flag = false;
- int result = -1;// 表示当用户执行添加删除和修改的时候所影响数据库的行数
- // 创建一个 PreparedStatement 对象来将参数化的 sql 语句发送到数据库。
- preparedStatement = connection.prepareStatement(sql);
- int index = 1;
- if (params != null && !params.isEmpty()) {
- for (Object object : params) {
- // 使用给定对象设置指定参数的值。index从1开始
- preparedStatement.setObject(index++, object);
- }
- }
- // 在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言语句,比如
- // INSERT、UPDATE 或 DELETE 语句
- result = preparedStatement.executeUpdate();
- flag = result > 0 ? true : false;
- return flag;
- }
- /**
- * 查询返回单条记录
- *
- * @param sql
- * @param params
- * @return
- * @throws SQLException
- */
- public Map<String, Object> findSimpleResult(String sql, List<Object> params)
- throws SQLException {
- Map<String, Object> map = new HashMap<String, Object>();
- int index = 1;
- // 创建一个 PreparedStatement 对象来将参数化的 sql 语句发送到数据库。
- preparedStatement = connection.prepareStatement(sql);
- if (params != null && !params.isEmpty()) {
- for (Object object : params) {
- // 使用给定对象设置指定参数的值。index从1开始
- preparedStatement.setObject(index++, object);
- }
- }
- // 在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。
- resultSet = preparedStatement.executeQuery();
- // 获取此 ResultSet 对象的列的编号、类型和属性。
- ResultSetMetaData metaData = resultSet.getMetaData();
- int col_len = metaData.getColumnCount();
- while (resultSet.next()) {
- for (int i = 0; i < col_len; i++) {
- // sql数据库列的下标是从1开始的
- String col_name = metaData.getColumnName(i + 1);
- Object col_value = resultSet.getObject(col_name);
- if (col_value == null) {
- col_value = "";
- }
- map.put(col_name, col_value);
- }
- }
- return map;
- }
- public List<Map<String, Object>> findMoreResult(String sql,
- List<Object> params) throws SQLException {
- List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
- int index = 1;
- // 创建一个 PreparedStatement 对象来将参数化的 sql 语句发送到数据库。
- preparedStatement = connection.prepareStatement(sql);
- if (params != null && !params.isEmpty()) {
- for (Object object : params) {
- // 使用给定对象设置指定参数的值。index从1开始
- preparedStatement.setObject(index++, object);
- }
- }
- // 在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。
- resultSet = preparedStatement.executeQuery();
- // 获取此 ResultSet 对象的列的编号、类型和属性。
- ResultSetMetaData metaData = resultSet.getMetaData();
- int col_len = metaData.getColumnCount();
- while (resultSet.next()) {
- Map<String, Object> map = new HashMap<String, Object>();
- for (int i = 0; i < col_len; i++) {
- // sql数据库列的下标是从1开始的
- String col_name = metaData.getColumnName(i + 1);
- Object col_value = resultSet.getObject(col_name);
- if (col_value == null) {
- col_value = "";
- }
- map.put(col_name, col_value);
- }
- list.add(map);
- }
- return list;
- }
- /**
- * 关闭数据库
- *
- * @throws SQLException
- */
- public void releaseConn() throws SQLException {
- if (resultSet != null) {
- resultSet.close();
- }
- if (preparedStatement != null) {
- preparedStatement.close();
- }
- if (connection != null) {
- connection.close();
- }
- }
- static JdbcUtils jdbcUtils;
- public static void main(String[] args) throws SQLException {
- jdbcUtils = new JdbcUtils();
- jdbcUtils.getConnection();
- // insert();
- // update();
- // query();
- Morequery();
- }
- private static void query() throws SQLException {
- String sql = "select * from userinfo where pwd = ? ";
- List<Object> params = new ArrayList<Object>();
- params.add("123");
- Map<String, Object> map = jdbcUtils.findSimpleResult(sql, params);
- System.out.println(map);
- }
- private static void Morequery() throws SQLException {
- String sql = "select * from userinfo ";
- List<Map<String, Object>> map = jdbcUtils.findMoreResult(sql, null);
- System.out.println(map);
- }
- /**
- * 更新数据库内容
- *
- * @throws SQLException
- */
- private static void update() throws SQLException {
- String sql = "update userinfo set username =? where id=2";
- List<Object> params = new ArrayList<Object>();
- params.add("liumr");
- jdbcUtils.updateByPrepareStatement(sql, params);
- }
- /**
- * 增加数据
- *
- * @throws SQLException
- */
- private static void insert() throws SQLException {
- String sql = "insert userinfo (username,pwd) values (?,?)";
- List<Object> params = new ArrayList<Object>();
- params.add("liugx");
- params.add("456");
- jdbcUtils.updateByPrepareStatement(sql, params);
- }
- }
数据库连接池技术
- 由于我们要对数据库频繁地进行操作,每进行一次连接操作就要获取一个conntection连接,每次使用完毕后要全部关闭资源,这样的话我们可以使用数据库连接池技术
- 优点:
- 资源重用:避免重复创建,释放连接,大量节约性能开销
- 更快的响应:在连接池初始化的过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间。
- 新的资源分配手段: 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源
- 统一的连接管理,避免数据库连接泄露: 在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。
- 创建的数据库连接池
- DBCP:由于性能问题,已经很少使用了
- C3P0:目前在很多项目中都在使用
- Druid(阿里巴巴):阿里巴巴开源的一个数据库连接池
- 下面我们示范常用的C3p0的使用
- 导入jar包c3p0-0.9.1.2.jar
- 在项目src目录下新建c3p0.properties
- 文件内容(当然还有很多其他配置,下面最简单配置)
- c3p0.driverClass=com.mysql.jdbc.Driver
- c3p0.jdbcUrl=jdbc:mysql://localhost:3306/test
- c3p0.user=root
- c3p0.password=root
- c3p0.driverClass=com.mysql.jdbc.Driver
- 在与数据库交互时
- //创建一个数据库连接池ComboPooledDataSource ds = new ComboPooledDataSource();
- //创建QueryRunner接口
- QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
- //通过接口可以执行查询或者更新,修改操作
- qr.update(sql); //返回受影响的行数
- qr.query(sql, null); //返回各种类型
- //创建一个数据库连接池ComboPooledDataSource ds = new ComboPooledDataSource();
- 关于QueryRunner的query方法其实功能是很强大的,可以根据查询的内容自动封装各种类型
- 封装入一个javaBean中
- public Category getById(String cid) throws Exception {
- QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
- String sql = "select * from category where cid = ?";
- return qr.query(sql, new BeanHandler<>(Category.class), cid);
- }
- public Category getById(String cid) throws Exception {
- 封装成一个可以指定类型的list集合
- public List<Category> findAll() throws Exception {
- QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
- String sql = "select * from category";
- List<Category> list = qr.query(sql, new BeanListHandler<>(Category.class));
- return list;
- }
- public List<Category> findAll() throws Exception {
- 返回单条数据
- /**
- * 查询数据总条数
- */
- @Override
- public Integer getTotalSize() throws Exception {
- // 创建查询接口
- QueryRunner qr = new QueryRunner(DataSourceUtils.getDataSource());
- String sql = "select count(*) from links";
- return ((Long) qr.query(sql, new ScalarHandler())).intValue();
- }
- /**
- C3p0是在项目中是很详细的,详细的学习该请大家参考正式的文档
- 关于QueryRunner的query方法其实功能是很强大的,可以根据查询的内容自动封装各种类型
厚积薄发系列之JDBC详解的更多相关文章
- JDBC详解系列(二)之加载驱动
---[来自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- 在JDBC详解系列(一)之流程中 ...
- JDBC详解系列(三)之建立连接(DriverManager.getConnection)
在JDBC详解系列(一)之流程中,我将数据库的连接分解成了六个步骤. JDBC流程: 第一步:加载Driver类,注册数据库驱动: 第二步:通过DriverManager,使用url,用户名和密码 ...
- JDBC详解1
JDBC详解1 JDBC整体思维导图 JDBC入门 导jar包:驱动! 加载驱动类:Class.forName("类名"); 给出url.username.password,其中u ...
- Spring4 JDBC详解
Spring4 JDBC详解 在之前的Spring4 IOC详解 的文章中,并没有介绍使用外部属性的知识点.现在利用配置c3p0连接池的契机来一起学习.本章内容主要有两个部分:配置c3p0(重点)和 ...
- JDBC详解(一)
一.相关概念介绍 1.1.数据库驱动 这里驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡,同样道理 ...
- Java基础-面向接口编程-JDBC详解
Java基础-面向接口编程-JDBC详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JDBC概念和数据库驱动程序 JDBC(Java Data Base Connectiv ...
- nginx高性能WEB服务器系列之四配置文件详解
nginx系列友情链接:nginx高性能WEB服务器系列之一简介及安装https://www.cnblogs.com/maxtgood/p/9597596.htmlnginx高性能WEB服务器系列之二 ...
- mongo 3.4分片集群系列之六:详解配置数据库
这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...
- mongo 3.4分片集群系列之五:详解平衡器
这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...
随机推荐
- python3的pip管理器pip3
一且因为python2到3的痛苦升级,python3的pip程序也有一个别致的名字pip3 安装: apt-get install python3-pip 安装后不能直接使用pip,否则会提示没有安装 ...
- The Report Of Twisted’s Death or: Why Twisted and Tornado Are Relevant In The Asyncio Age
Speech on PyCon2016 https://www.youtube.com/watch?v=82vuCZ4FLFE
- Cocos2d-x 3.4 初体验——安装教程
电脑系统window7 32位 1.首先从官网下载cocos2d-x并解压 http://cn.cocos2d-x.org/download/ 解压后的文件夹中有一个setup.py,双击运行.需要安 ...
- rsync 精确同步文件用法 (转载)
-- include-from 指定目录下的部分目录的方法: include.txt: aa bb ss Command: rsync -aSz --include-from=/home/inclu ...
- eclipse开发cocos2dx 3.2环境搭建之中的一个: Android C\C++环境搭建(ndk r9d)
这几天有时间,琢磨一下cocos2dx.cocos2d家族事实上挺庞大的.也有cocos2d-android这样的能够直接用Java语言来开发的,可是cocos2d-android资料相对少一些.并且 ...
- Unix系统编程()虚拟内存管理
在之前学到过进程的内存布局中忽略了一个事实:这一布局存在于虚拟文件中. 因为对虚拟内存的理解将有助于后续对fork系统调用.共享内存和映射文件之类的主题阐述,这里还要学习一下有关虚拟内存的详细内容. ...
- [uboot]uboot如何引导系统
转自:http://bbs.elecfans.com/jishu_455028_1_1.html 如6410的bootcmd和bootargs默认存在于uboot1.1.6/include/confi ...
- 示例 - C#脚本代码采集搜狐NBA球员, 球队和比赛实况
最近 @甜瓜 (QQ:1069629945) 开发了一套NBA数据采集脚本, 我觉得很赞. 经他允许发布出来和大家分享一些经验: 球员球队: http://data.sports.sohu.com/n ...
- 介绍编译的less的几种IDE工具
介绍编译的less的两种IDE工具 现在css预编译越来越普及了,著名的有less.sass.stylus等等等等.功能上基本上都是大同小异.这些个玩意儿主要表达的意思就是:“像编程一样的编写你的cs ...
- Entity Framework(五):使用配置伙伴创建数据库
在上一篇文章中讲了如何使用fluent API来创建数据表,不知道你有没有注意到一个问题.上面的OnModelCreating方法中,我们只配置了一个类Product,也许代码不是很多,但也不算很少, ...