JDBC技术

本文详细介绍了JDBC技术,包括其概念、基本步骤、静态和动态Statement的使用,JDBC的基本操作如返回主键、批量操作和事务处理,以及连接池的运用,特别是Druid连接池的配置和使用。此外,还讲解了Apache DBUtils如何简化数据库CURD操作,以及封装BaseDao的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JDBC技术

一、介绍和理解

1、JDBC【java database connectivity】的概念:

  1. Java连接数据库的技术!
  2. Java连接数据的规范!
  3. JDBC由两部分组成:Java的规范【java.sql.接口】jdk、数据库厂商提供的实现类jar【实现类 基于 接口】
  4. Java.sql.接口=各个数据库的实现类;

2、JDBC的理解:
a.jdbc就是一套Java的规范+数据库的实现
b.我们只需要学习接口中的方法,不需要关注具体的实现!
c.可以无感切换数据库!mysql -oracle只需要切换jar即可

3、JDBC设计的接口和类
a.DriverManager
b.Driver 安装第三方数据的驱动!引入jar包
c.Connection Java陈鼓型和数据库建立的连接!在连接的基础上可以继续sql语句的执行操作
d.Statement 包装一条sql语句,发送到数据库。并待会执行结果resulteset
e.ResultSet 结果集,执行sql语句的结果的duixiang!内部的接口行和列

二、基本步骤

  1. 注册驱动
  2. 创建连接
  3. 创建statement
  4. 编写sql语句
  5. statement执行sql语句,并返回值
  6. 解析resultset数据
  7. 释放资源
    在这里插入图片描述

三、基于静态Statement使用

  1. 非DQL(数据库查询操作)操作
//1. 注册驱动
//触发两次注册驱动!
/**
 * 1. 外部注册DriverManager.registerDriver(new Driver())
 * 2. 内部注册 Driver - static{ 被触发一次 }
 */

// DriverManager.registerDriver(new Driver())
// 加载类  Class.forName("字符串 类的全限定符")
Class.forName("com.mysql.jdbc.Driver");

//2. 获取连接
/**
 * 获取连接:
 *    Java程序和数据的桥梁!
 *    cmd - mysql  mysql -u账号 -p密码 -P port -h ip地址
 *    小海豚 - mysql  账号 密码 port ip
 *    java - mysql 账号 密码 port ip
 *    url链接 - 统一资源定位符  协议 :// host : port
 *            jdbc:数据库厂商://ip:port/数据库?k=v
 *            jdbc:mysql://localhost:3306/test1 = jdbc:mysql:///test1
 *
 *    file:///
 *    tpc://
 *    content://
 *    http:// 网络请求协议
 *    jdbc协议:  jdbc:mysql   jdbc:oracle
 *
 */
java.sql.Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test1",
        "root", "root");

Properties properties = new Properties();
//传入的参数key是固定的!
properties.setProperty("user","root");
properties.setProperty("password","root");

java.sql.Connection connection_properties =
        DriverManager.getConnection("jdbc:mysql://localhost:3306/test1",properties);

//url  协议 :// host : port ? key = value  & key = value
java.sql.Connection connection_url =
        DriverManager.getConnection("jdbc:mysql://localhost:3306/test1?user=root&password=root");

//3. 创建statement

java.sql.Statement statement = connection.createStatement();

//4. 编写sql语句

String sql = "delete from a where aid = 1;";

//5. statement执行sql语句
//rows 返回影响行数  删除3行数据 - rows = 3
int rows = statement.executeUpdate(sql);

System.out.println("rows = " + rows);
//6. 释放资源

if (statement != null) {
    statement.close();
}

if (connection != null) {
    connection.close();
}

  1. DQL操作
 Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://localhost:3306/market";
        String user = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, user, password);

        //3.创建statement
        Statement statement = connection.createStatement();

        //4.写sql语句
        String sql ="select * from emp";

        //5.执行sql语句并获取resultset
        //DQL以外的sql语句
        //DML返回的影响行数!  DDL  TPL  DCL  ->0
        //statement.executeUpdate();
        /**
         * TODO:resultSet 内部装的就是查询返回的虚拟数据表!由表头+数据组成
         * TODO:数据可能没有值,但是表头绝对存在
         */

        ResultSet resultSet = statement.executeQuery(sql);

        //6.解析结果
        /**
         * todo:方案一:获取empno员工编号
         * todo:移动光标
         *    next() return boolean
         *    默认情况下,光标指向第一行数据之前,
         *    移动光标可以将它指向数据!【current row】
         *    getString getInt getXxx getObject 获取【current row】的数据!
         *    return 解释,有更多行,移动光标到下一行,并返回true,如果没有更多行
         *    返回false
         */
//            resultSet.next();
         /**
          *
          * todo:获取当前行的数据
          * getXxx(int columnIndex[1....]/String columnlabel)
          * */
//        while (resultSet.next()) {
//
//            String empno = resultSet.getString("empno");
//            System.out.println("empno = " + empno);
//
//        }
        System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++");
        /**
         * todo:方案二获取empno信息
         */
        //表头信息  :列数和列名
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();
        //获取列名,不需要移动光标
        //index-列的下角标,用来获取列名
        //metaData.getColumnName(int index)获取列名
        //metaData.getColumnLabel(int index)起别名获取别名反之列名【推荐】

        while (resultSet.next()) {
            //todo;列名
//            resultSet.getString("empno");
//            resultSet.getString("ename");
//            resultSet.getString("mgr");
            for (int i = 1; i <= columnCount; i++) {
                //获取别名
                String value = resultSet.getString(i);
                String columnName = metaData.getColumnName(i);
                String columnLabel = metaData.getColumnLabel(i);
                System.out.println(columnName+" = " + value+" = "+columnLabel);
            }

        }
        //7.关闭资源
        resultSet.close();
        if (statement != null) {
            statement.close();
        }
        if (connection != null) {
            connection.close();
        }

四、基于动态Statement使用

动态模拟登陆

 public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1、注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2、获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///market", "root", "root");

        //3、创建预编译statement
        //结构sql语句!值得部分用?代替,?是站为辅的意思
        String sql ="select * from USER where account =? and PASSWORD =?;";

        PreparedStatement preparedStatement = connection.prepareStatement("sql");

        //4、占位赋值
        /**
         * 参数一:?的下角标 从一开始,从左开始
         */
        System.out.println("请输入账号!");
        Scanner sc = new Scanner(System.in);
        String account = sc.nextLine();
        System.out.println("请您输入密码!");
        String pwd = sc.nextLine();

        preparedStatement.setObject(1,account);
        preparedStatement.setObject(2,pwd);

        //5、执行sql语句,不需要指明sql语句
        ResultSet resultSet = preparedStatement.executeQuery();

        //sql  :关键字 函数 容器名  ‘字符’

        //6、解析结果集
        ResultSetMetaData metaData = resultSet.getMetaData();
        int columnCount = metaData.getColumnCount();

        while (resultSet.next()) {
            for (int i = 1; i < columnCount; i++) {
                String string = resultSet.getString(i);

                System.out.println("string = " + string);
            }
        }


        //6、解析结果集

        //7、关闭资源
        resultSet.close();
        if (preparedStatement != null) {
            preparedStatement.close();
        }
        if (connection != null) {
            connection.close();
        }
    }

五、JDBC的基本使用

1 . 返回主键编号

 //1、注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2、获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///market", "root", "root");

        //3、sql结构
        String sql = "insert into user (nickname,account,PASSWORD)values (?,?,?)";

        //4、预编译(动态statement)
        PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

        //5、占位符赋值

        preparedStatement.setObject(1,"朱停");
        preparedStatement.setObject(2,"root1");
        preparedStatement.setObject(3,"root");
        //6、执行sql
        int rows = preparedStatement.executeUpdate();
        //返回值  单行单列
        ResultSet generatedKeys = preparedStatement.getGeneratedKeys();

        if (rows>0) {
            System.out.println("注册成功");
            generatedKeys.next();
            int keysInt = generatedKeys.getInt(1);
            System.out.println("keysInt = " + keysInt);
        }
        //7、关闭资源
        preparedStatement.close();
        connection.close();

2 . 批量操作

 //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///test1?rewriteBatchedStatements=true", "root", "root");

        //3.sql结构
        String sql = "insert into user (nickname,account,password) values (?,?,?)";

        //4.预编译动态statement
        //设置想要获取返回生成keys
        PreparedStatement statement = connection.prepareStatement(sql);

        long start = System.currentTimeMillis();

        for (int i = 0; i < 1000; i++) {


            //5.占位符赋值
            statement.setObject(1, "吴邪"+i);
            statement.setObject(2, "wuxie1"+i);
            statement.setObject(3, "root");

            statement.addBatch();
            //int rows = statement.executeUpdate();
        }

        //6.执行sq
        int[] rows = statement.executeBatch();
        //
        System.out.println(Arrays.toString(rows));


        long end = System.currentTimeMillis();

        System.out.println("time = " + (end - start));



        //7.关闭资源

        statement.close();
        connection.close();
    }

3 . 事物务操作

package com.atguigu.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * @description TODO:sql的实务操作
 *                   1、关闭自动提交  手动提交个【提交和回滚】
 *                      show  variable  like "%autocommit%"#关闭了自动提交只在当前连接有效
 *                      set autocommit = off;
 *                      sql
 *                      sql
 *                      commit/rollback;
 *                  2、主动开启一个事务  手动提交【提交和回滚】
 *                      start transaction;
 *                      sql
 *                      sql
 *                      sql
 *                      commit/rollback;
 *                  jdbc的事务操作
 *                      jdbc基于的关闭自动提交
 *                      connection默认自动提交事物
 *                      connection.setAutoCommit(false)
 *                      statement connection.preparedStatment(); sql
 *                      statement connection.preparedStatment(); sql
 *                      connection.commit() / rollback();
 *           注意: 一个事务的statement必须由同一个connection创建!
 *
 *
 * @atuthor ${Mr.W}
 * @create 2021/11/28  21:33
 */
public class jdbcTransaction {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1、注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2、获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///market", "root", "root");
        //关闭自动提交
        connection.setAutoCommit(false);

        try {
            //3、写sql语句
            String  sql_add ="update account set money =money+10000 where aname ='wy'";
            String  sql_sub ="update account set money =money-10000 where aname ='mayun'";

            //4、预编译
            PreparedStatement preparedStatement = connection.prepareStatement(sql_add);
            int i = preparedStatement.executeUpdate();
            System.out.println("wy加钱= " + i);

            PreparedStatement preparedStatement1 = connection.prepareStatement(sql_sub);
            int i1 = preparedStatement1.executeUpdate();
            System.out.println("mayun减钱 = " + i1);

            connection.commit();
        }catch (SQLException e){
            e.printStackTrace();
            connection.rollback();
        }



        //5、关闭资源
        connection.close();
    }
}

六、链接池使用

  1. 连接池介绍
  2. druid连接池使用
    a. 直接创建 【硬编码】

```sql
private static DruidDataSource dataSource = new DruidDataSource();

static {

    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl("jdbc:mysql:///test1");
    dataSource.setUsername("root");
    dataSource.setPassword("root");

    //3.设置可选属性,连接池的初始化容量  最大容量  等待时间【到达最大数量】
    dataSource.setInitialSize(5);
    dataSource.setMaxActive(10);
    dataSource.setMaxWait(1000);
}

b. 工厂创建 【软编码】
private static DataSource dataSource = null;

static {

    Properties properties = new Properties();
    InputStream asStream = JdbcPool.class.getClassLoader().getResourceAsStream("jdbc.properties");

    try {
        properties.load(asStream);
        dataSource = DruidDataSourceFactory.createDataSource(properties);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

  1. druid工具类封装 [今天实现的第三个案例]
    a. 编写外部配置文件
    src/jdbc.properties
#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test1
username=root
password=root
initialSize=5
maxActive=10
maxWait=1000

b. 编写连接池工具类
package com.atguigu.datasource;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * projectName: day04_jdbc
 *
 * @author: 赵伟风
 * time: 2021/11/26 17:09
 * description:基于Druid连接池进行连接的获取和回收!
 *     todo 基于外部的配置文件!
 */
public class JdbcPoolV2 {

    private static DataSource dataSource = null;

    static {

        Properties properties = new Properties();
        InputStream asStream = JdbcPool.class.getClassLoader().getResourceAsStream("jdbc.properties");

        try {
            properties.load(asStream);
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 获取连接连接的方法
     * @return 返回连接池中的连接
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {

        return dataSource.getConnection();
    }


    /**
     * 回收连接
     * @param connection 需要回收的连接! 注意,必须是连接池取出的连接
     * @throws SQLException
     */
    public static void  close(Connection connection) throws SQLException{

        if (connection != null) {
            connection.close();
        }

    }
}

七、ApacheDBUtils

  1. 介绍
    a. jdbc 【获取连接和数据库的curd】
    b. druid 【优化获取连接】
    c. dbutils 【简化数据库curd】
  2. 非DQL
/**
 * DML
 */
@Test
public void  testCUD() throws SQLException {

    //apache dbutils提供的数据的curd的工具api
    QueryRunner queryRunner = new QueryRunner();

    String sql = "insert into a (aid,aname) values (?,?);";

    /**
     * update DDL DML DCL TPL
     * return int
     * 参数:
     *   1.connection
     *   2.sql
     *   3.Object...params ? 占位符值 可变参数!参数要和sql语句中的?顺序一一对应!
     */
    //连接池
    Connection connection = JdbcPoolV2.getConnection();

    // = 1. 创建preparedStatement  2.setObject占位符赋值  3.执行sql executeUpdate()
    int rows = queryRunner.update(connection, sql, "10", "呵呵");

    System.out.println("rows = " + rows);
    connection.close();

}

  1. DQL
/**
 * apache DBUtils DQL
 */
@Test
public void   testRead() throws SQLException {

    //1.创建dbutils对象 queryrunner

    QueryRunner queryRunner = new QueryRunner();

    String sql = "select * from a where aid > ?;";

    /**
     * query执行查询语句!
     *   参数1: connection
     *   参数2: sql
     *   参数3: rsh -> ResultSetHandler 结果集处理器 - table - class  一行数据 - 一个对象  resultSet -> 想要的结果
     *      1.返回一个map
     *        select * from a where aid = 1;
     *        aid  aname
     *         1    xx
     *        map - aid - 1 / aname - xx
     *   参数4: Object...params
     *
     */
    Connection connection = JdbcPoolV2.getConnection();

    // queryRunner.query = 1.创建statement 2.占位符  3.执行sql语句 4.结果集解析
    // Map<String, Object> map = queryRunner.query(connection, sql, new MapHandler(), 1);
    List<Map<String, Object>> list = queryRunner.query(connection, sql, new MapListHandler(), 1);

    System.out.println("list = " + list);

    connection.close();


}

/**
 * 查询数据库数据使用对象接值
 * @throws SQLException
 */
@Test
public void   testReadToEntity() throws SQLException {

    //1.创建dbutils对象 queryrunner

    QueryRunner queryRunner = new QueryRunner();

    String sql = "select * from a where aid > ?;";


    Connection connection = JdbcPoolV2.getConnection();

    /**
     * 如果想要返回对象请使用 BeanHandler / BeanListHandler(class)
     */
    List<A> a = queryRunner.query(connection, sql, new BeanListHandler<>(A.class), 1);

    System.out.println("a = " + a);

    connection.close();


}

八、封装BaseDao

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值