JDBC

1、JDBC

概念:

JDBC(Java Database Connectivity) , Java连接数据库的规范(标准)。

使用JDBC连接数据库完成CRUD操作。

核心思想:

Java中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。

由数据库厂商提供驱动实现类(Driver数据库驱动)。

MySQL数据库驱动

mysql-connection-java-5.1.X 适用于5.X版本

mysql-connection-java-8.0.X 适用于8.X版本


2、JDBC开发步骤

开发步骤:

 


3、ResultSet

概念:

        在执行查询SQL后,存放查询到的结果集数据。

接受结果集:

 注意:

        作用就是完成了查询结果的存储功能,而且只能读取一次,不能够来回的滚动读取

遍历ResultSet:

        ResultSet以表结构进行临时结果的存储,通过JDBC API将其中数据进行依次获取

 经验:

        getXxx方法可以获取的类型有:基本数据类型、引用数据类型


4、常见错误


5、SQL注入

原因:

        用户输入的数据中有SQL关键字或语法并且参与了SQL语句的编译,导致SQL语句编译后的条件含义为true,一直得到正确的结果。这种现象称为SQL注入。

如何避免:

        由于编写的SQL语句是在用户输入数据,整合后再进行编译

        我们要使SQL语句在用户输入数据前就已编译成完整的SQL语句,再进行填充数据。


6、PreparedStatement

概念:

        PreparedStatement继承了Statement接口,执行SQL语句的方法无异

作用:

        预编译SQL语句,效率高

        安全,避免SQL注入

        可以动态的填充数据,执行多个同构的SQL语句

应用:

预编译SQL语句,参数使用?占位

 为参数下标赋值:

 注意:

        在JDBC中的所有参数都由?符号占位,这被称为参数标记

        在执行SQL语句之前,必须为每个参数提供值


6、封装工具类

背景:

        在JDBC的使用中,连接数据库、关闭连接等存在着大量的重复代码

        把传统的JDBC代码进行重构,抽取出通用的JDBC工具类

重用性方案:

        封装获取连接方法

         封装释放资源方法

背景:

        重用性方案中的参数都是硬编码,当驱动、URL等参数需要更换时,需要重新编译

        通过配置文件读取配置信息,使用软编码方式,更灵活的方案

跨平台方案:

        创建properties配置文件

        创建Properties集合:

                public static final Properties prop = new Properties();

        静态代码块中,使用输入流,读取配置文件


7、ORM

概念:

        Object Relational Mapping:对象映射关系

        对结果集(ResultSet)遍历时,取出的都是零散的数据

        在实际应用开发中,我们需要将零散的数据进行封装整理

实体类(Entity):

        一行数据中,多个零散的数据进行整理

        通过entity的规则对表中的数据进行对象的封装

        表名=类名  列名=属性名 提供各个属性的set get方法

        提供无参构造方法(视情况添加有参构造)


8、DAO

 概念;

        Data Access Object : 数据访问对象。

        DAO实现了业务逻辑与数据库访问相分离

        对同一张表的所有操作封装在XxxDaoimpl对象中。

        根据增删改查提供具体的方法(insert、update、delete、select、selectAll)


9、Service

什么是业务?

        代表用户完成的一个业务功能,可以由一个或多个DAO的调用组成

        软件所提供的一个功能叫业务

 


10、事务

概念:

        事务是一个原子操作。是一个最小执行单元。由一个或多个SQL语句组成

        在同一个事务当中,所有的SQL语句都成功执行时,整个事务成功

        在一个SQL语句执行失败,整个事务都执行失败

事物的边界:

        在JDBC中,先获得Connection对象。

        开始事务:conn.setAutoCommit(false);

        手动提交事务:conn.commit();

        手动回滚事务:conn.rollback();

在Service中,调用了多次DAO操作。每一个业务功能都要控制事务。

 问题:

当程序发生异常时,事务回滚并没有成功。

原因:

        Service控制事务和DAO访问数据库时的连接对象,并非同一个。

 在一个业务流程中,要保证多个数据库访问操作的连接对象是同一个

连接对象的同步方案1:

将Connection对象通过Service获取并传递给各个DAO方法。

传递的问题:

如果使用传递Connection,容易造成接口污染(BadSmell)

定义接口是为了更容易更换实现,而将Connection定义在接口中,会污染当前接口

连接对象同步方案2:

可以将整个线程中(单线程)中,存储一个共享值

线程拥有一个类似Map的属性,键值对结构<ThreadLocal对象,值>。


11、ThreadLocal

 


12、事物的封装

现有问题:

        事务的开启、提交、回滚的代码都现在了Service中。

        Service的主要职责是模拟现实业务功能。要将事务的控制封装在工具类中

工具类封装事务控制方法:

开启事务:

        begin();

提交事务:

        commit();

回滚事务;

        rollback();


13、三层架构

现有问题:在之前学习过程中,通过DAO与Service对象实现数据访问与业务逻辑的分离

面向实现类编程: 层与层之间的耦合度高、不易修改、扩展、更换实现。

程序设计时,要考虑易修改、易扩展

为Service层和DAO层设计接口,便于未来更换实现类


14、DaoUtils

现有问题:

        在DAO层中,对数据库表的增、删、改、查操作存在代码冗余

        可对其进行抽取封装DaoUtils工具类实现复用。

增删改方法:

        相同:获取连接,预编译SQL、占位符赋值、执行并返回结果。

        不同:sql语句不同、参数列表不同

将DAO中增删改的数据库访问操作进行封装

查询方法:

        相同:获取连接、预编译SQL、占位符赋值、执行并返回结果

        不同:sql语句不同、参数列表不同、返回的结果不同(单个对象或集合、对象类型)

封装问题:

        方法返回值类型

        方法的参数列表

        如何封装对象

        方法中如何返回单个对象或多个对象

工具类无法同时完成执行查询、封装对象、返回结果的操作。


15、数据库连接池

现有问题:

        数据库连接是一种关键的、有限的、昂贵的资源

        频繁的创建、关闭会影响程序的性能

连接池:

        数据库连接池负责分配、管理和释放数据库连接

        在程序初始化时,预先创建指定数量的数据库连接对象存储在池中

        避免频繁的创建、关闭

 

 


16、DbUtils

概念:

        Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库

        使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能

作用:

        小巧、简单、实用。

        对于数据表的查询操作,可以把结果转换为List 、Array 、 Set等集合

        对于数据表的DML操作,只需要写SQL语句

17、 综合

UTIL

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;

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

public class DBUtil {
    //声明局部线程类:保存自己的连接
    //类map集合  key是线程id  value 是connection对象
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
    //声明连接池对象:提升获取连接的效率
    private static DruidDataSource dataSource;

    static {
        InputStream inputStream = DbUtils.class.getResourceAsStream("/db.properties");
        Properties properties = new Properties();
        try {
            properties.load(inputStream);
            //创建连接池对象
            dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        //到连接池中获取连接
        //第一步:先到局部线程类中获取自己原有的连接
        //第二步:判断是否获取到,如果获取到,则使用获取到的,如果没有获取到自己原来的连接,那么到连接池获取
        Connection connection = threadLocal.get();
        if (connection == null) {
            //没有获取到自己线程使用的connection对象

            try {
                //从连接池获取
                connection = dataSource.getConnection();
                //存入局部线程
                threadLocal.set(connection);
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
        return connection;
    }

    //返回连接池对象
    public static DataSource getDataSource() {
        return dataSource;
    }
}


18、总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值