jdbc

Posted bbs1234

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jdbc相关的知识,希望对你有一定的参考价值。

JDBC

今日任务

  • 使用JDBC完成对分类表CRUD的操作(JDBC的回顾)
  • 使用DBCP,C3P0连接池完成基本数据库的操作(抽取工具类)
  • 能够使用DBUtils完成CRUD的操作

 

教学导航

教学目标

掌握DBCPC3P0连接池的使用并掌握连接池的原理.

能够使用DBUtils完成基本的CRUD的操作

教学方法

案例驱动法

1.1 使用JDBC完成对于分类的CRUD的操作-回顾JDBC

1.1.1 需求:

网上商城中对分类添加,修改,删除,查询的操作.使用JDBC完成对分类的CRUD的操作.

1.1.2 分析:

1.1.2.1 技术分析

JDBC的回顾】

  • JDBC的概念:

JDBCJava Data Base Connectivity.

  • 驱动:

 

  • JDBC的开发步骤:

步骤一:注册驱动.

步骤二:获得连接.
步骤三:创建执行SQL语句对象.

步骤四:释放资源.

  • JDBCAPI的详解:

DriverManager

    * 注册驱动:

    * 获得连接:

Connection

    * 获得执行SQL语句对象.

        * Statement createStatement();

        * PreparedStatement prepareStatement(String sql);

        * CallableStatement prepareCall(String sql);

    * 进行事务管理:

        * setAutoCommit(boolean flag);

        * commit();

        * rollback();

Statement:

    * 执行SQL语句:

        * int executeUpate(String sql); --执行insert update delete语句.

        * ResultSet executeQuery(String sql); --执行select语句.

        * boolean execute(String sql); --执行select返回true 执行其他的语句返回false.

  

ResultSet:

    * 遍历结果集:next();

    * 获得结果集中的数据.getXXX(int c); getXXX(String name);

1.1.2.2 步骤分析

  • 步骤一:创建Java项目,引入mysql的驱动包.
  • 步骤二:编写程序
  • 步骤三:注册驱动
  • 步骤四:获得连接
  • 步骤五:执行SQL
  • 步骤六:释放资源

1.1.3 代码实现:

抽取工具类:

package com.itheima.jdbc.utils;

 

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

import java.util.Properties;

 

/**

 * JDBC的工具类

 * @author apple

 *

 */

public class JDBCUtils {

public static final String DRIVERCLASS;

public static final String URL;

public static final String USERNAME;

public static final String PASSWORD;

 

static{

// 获得属性文件中的数据.

Properties properties = new Properties();

try {

properties.load(new FileInputStream("src/db.properties"));

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

 

DRIVERCLASS = properties.getProperty("jdbc.driverClass");

URL = properties.getProperty("jdbc.url");

USERNAME = properties.getProperty("jdbc.username");

PASSWORD = properties.getProperty("jdbc.password");

}

 

// 加载驱动:

public static void loadDriver(){

try {

Class.forName(DRIVERCLASS);

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

 

// 获得连接:

public static Connection getConnection(){

loadDriver();

Connection conn = null;

try {

conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return conn;

}

 

// 释放资源:

public static void release(Statement stmt,Connection conn){

if(stmt != null){

try {

stmt.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

stmt = null;

}

 

if(conn != null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

 

public static void release(ResultSet rs,Statement stmt,Connection conn){

if(rs!= null){

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

rs = null;

}

if(stmt != null){

try {

stmt.close();

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

stmt = null;

}

 

if(conn != null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

conn = null;

}

}

}

 

1.2 使用连接池改造JDBC的程序:

1.2.1 需求:

提升程序运行的效率,采用连接池对JDBC的部分的效率进行提升.

1.2.2 分析:

1.2.2.1 技术分析:

【连接池的概述】

  • 为什么使用连接池

Connection对象在JDBC使用的时候.使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了.每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.程序初始化的时候,初始化多个连接,将多个连接放入到池中(内存中).每次获取的时候,都可以直接从连接池中进行获取.使用结束以后,将连接归还到池中.

  • 常见连接池:

DBCP :Apache.

C3P0 :

【连接池的原理】

javax.sql.DataSource接口--连接池的接口

* 功能:初始化多个连接.把多个连接放入到内存中.

* 归还:将连接对象放回到内存中.

【自定义连接池--了解】

public class MyDataSource implements DataSource{

 

// 创建一个集合List集合.

List<Connection> list = new ArrayList<Connection>();

 

// 初始化连接池的时候,初始化5个连接.

public  MyDataSource() {

for (int i = 1; i <= 5; i++) {

Connection conn = JDBCUtils.getConnection();

list.add(conn);

}

}

 

@Override

// 从连接池中获得连接

public Connection getConnection() throws SQLException {

if(list.size()==0){

for (int i = 1; i <= 3; i++) {

Connection conn = JDBCUtils.getConnection();

list.add(conn);

}

}

Connection conn = list.remove(0);

return conn;

}

 

// 归还连接:

public void addBack(Connection conn){

list.add(conn);

}

...

}

 

【自定义连接池中问题】

1.创建连接池的时候能不能面向接口编程.

2.额外增加连接池的方法,那么程序员需要记住这些方法.能不能不额外去提供一些方法.

***** 解决:就是要去增强Connectionclose方法.

       1.继承的方法:

            * 继承的使用条件:能够控制这个类的构造.

       2.装饰者模式:(*****)

            * 装饰者模式的使用条件:

                * 2.1增强的类和被增强的类实现相同的接口.

                * 2.2在增强的类中能够获得被增强的类的引用.

            * 接口中方法过多,只增强其中的一个方法.其他方法都需要原样调用原有方法.

       3.动态代理:(*****)

            * JDK的动态代理使用条件:

                 * 被代理的对象必须实现接口.

【使用开源连接池优化程序】

  • DBCP连接池:

 

核心API

 

 

@Test

/**

 * DBCP的一个入门:手动设置参数

 */

public void demo1(){

Connection conn = null;

PreparedStatement pstmt = null;

 

// 创建连接池:

BasicDataSource dataSource = new BasicDataSource();

dataSource.setDriverClassName("com.mysql.jdbc.Driver");

dataSource.setUrl("jdbc:mysql:///web07");

dataSource.setUsername("root");

dataSource.setPassword("1234");

try{

// 获得连接:

conn = dataSource.getConnection();

// 编写SQL语句.

String sql = "insert into category values (null,?)";

// 预编译SQL:

pstmt = conn.prepareStatement(sql);

// 设置参数:

pstmt.setString(1, "鞋靴箱包");

//执行SQL

pstmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(pstmt, conn);

}

}

 

@Test

/**

 * DBCP的带有配置文件的方式

 */

public void demo2(){

Connection conn = null;

PreparedStatement pstmt = null;

 

// 创建连接池:

try{

Properties properties = new Properties();

properties.load(new FileInputStream("src/dbcp.properties"));

DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);

// 获得连接:

conn = dataSource.getConnection();

// 编写SQL语句.

String sql = "insert into category values (null,?)";

// 预编译SQL:

pstmt = conn.prepareStatement(sql);

// 设置参数:

pstmt.setString(1, "生活用品");

//执行SQL

pstmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(pstmt, conn);

}

}

 

DBCP的参数的设置:

#连接设置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/jdbc

username=root

password=1234

 

#<!-- 初始化连接 -->

initialSize=10

 

#最大连接数量

maxActive=50

 

#<!-- 最大空闲连接 -->

maxIdle=20

 

#<!-- 最小空闲连接 -->

minIdle=5

 

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60-->

maxWait=60000

  • C3P0连接池的使用:

 

 

代码实现:

@Test

/**

 * 手动设置参数的方式:

 */

public void demo1(){

Connection conn = null;

PreparedStatement stmt = null;

// System.err.println("");

try{

// 创建连接池:

ComboPooledDataSource dataSource = new ComboPooledDataSource();

// 设置参数:

dataSource.setDriverClass("com.mysql.jdbc.Driver");

dataSource.setJdbcUrl("jdbc:mysql:///web07");

dataSource.setUser("root");

dataSource.setPassword("1234");

 

conn = dataSource.getConnection();

// 编写SQL

String sql = "insert into category values (null,?)";

// 预编译SQL:

stmt = conn.prepareStatement(sql);

// 设置参数:

stmt.setString(1, "食品饮料");

stmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(stmt, conn);

}

}

 

@Test

/**

 * 配置文件的方式:

 */

public void demo2(){

Connection conn = null;

PreparedStatement stmt = null;

// System.err.println("");

try{

// 创建连接池:

ComboPooledDataSource dataSource = new ComboPooledDataSource("mysql11111");

 

conn = dataSource.getConnection();

// 编写SQL

String sql = "insert into category values (null,?)";

// 预编译SQL:

stmt = conn.prepareStatement(sql);

// 设置参数:

stmt.setString(1, "食品饮料222");

stmt.executeUpdate();

}catch(Exception e){

e.printStackTrace();

}finally{

JDBCUtils.release(stmt, conn);

}

}

使用C3P0改写了工具类

public class JDBCUtils2 {

 

private static final ComboPooledDataSource DATASOURCE =new ComboPooledDataSource();

 

public Connection getConnection(){

Connection conn = null;

try {

conn = DATASOURCE.getConnection();

} catch (SQLException e) {

e.printStackTrace();

}

return conn;

}

     ...

}

1.3 DBUtils完成CRUD的操作

1.3.1 需求:

简化DAO的开发.

1.3.2 分析:

1.3.2.1 技术分析:

DBUtils

【概述】

DBUtilsjava编程中的数据库操作实用工具,小巧简单实用。

DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。

Dbutils三个核心功能介绍

l QueryRunner中提供对sql语句操作的API.

l ResultSetHandler接口,用于定义select操作后,怎样封装结果集.

l DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法

 

【QueryRunner核心类

l QueryRunner(DataSource ds) ,提供数据源(连接池),DBUtils底层自动维护连接connection

l update(String sql, Object... params) ,执行更新数据

l query(String sql, ResultSetHandler<T> rsh, Object... params) ,执行查询

 

【ResultSetHandler结果集处理类

ArrayHandler

将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值

ArrayListHandler

将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。

BeanHandler

将结果集中第一条记录封装到一个指定的javaBean中。

BeanListHandler

将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中

ColumnListHandler

将结果集中指定的列的字段值,封装到一个List集合中

KeyedHandler

将结果集中每一条记录封装到Map<String,Object>,在将这个map集合做为另一个Mapvalue,另一个Map集合的key是指定的字段的值。

MapHandler

将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值

 

MapListHandler

将结果集中每一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值,在将这些Map封装到List集合中。

ScalarHandler

它是用于单数据。例如select count(*) from 表操作。

 

【DbUtils】

closeQuietly(Connection conn) 关闭连接,如果有异常try后不抛。

commitAndCloseQuietly(Connection conn) 提交并关闭连接

rollbackAndCloseQuietly(Connection conn) 回滚并关闭连接

 


以上是关于jdbc的主要内容,如果未能解决你的问题,请参考以下文章

JDBCJDBC连接mySQL数据库常见错误

JDBCJDBC连接mySQL数据库常见错误

JDBC

关于JDBC小总结

java JDBC编程学习笔记

java JDBC编程学习笔记