JDBC的封装

10 篇文章 1 订阅
本文详细介绍了如何通过面向接口编程封装JDBC,包括创建数据库配置文件、定义实体类、设计接口、实现接口、创建数据库工具类以及应用单例模式。通过这种方式,提高了代码的可读性、可维护性和复用性,降低了不同数据库实现的耦合度。
摘要由CSDN通过智能技术生成

目录

JDBC封装的步骤:

1、在src里面创建一个文件,命名为:database.properties

2、定义实体类:实体类的表名与数据库的表名一致,表中大每一列为实体类的属性

3、将用户对象的所有操作抽取成接口

4、由不同数据库的实现类分别实现接口;实现类实现接口并继承数据库工具类

5、将通用的操作(如打开、关闭连接等)封装到工具类数据库工具类

6、在测试类进行测试

 7、单例模式



在编写JDBC时存在一些问题:

1、可读性差

2、不利于后期维护和修改

3、不利于代码复用

采用面向接口编程,可以降低代码间的耦合性

JDBC封装:

1、隔离业务逻辑代码和数据访问代码

2、隔离不同数据库的实现

JDBC封装的步骤:

1、定义实体类传输数据

2、将所有增删改查操作抽取

3、由不同数据库的实现类分别实现接口

4、将通用的操作(打开,关闭连接,增删改查等)封装到数据库工具类BaseDao的通用方法中

具体实现:

1、在src里面创建一个文件,命名为:database.properties

然后在里面添加一下数据

# 加载驱动
driver = com.mysql.jdbc.Driver
# 数据库地址
url = jdbc:mysql://127.0.0.1:3306/myschool
#用户名
username = root
#密码
password = root

2、定义实体类:实体类的表名与数据库的表名一致,表中大每一列为实体类的属性

//创建一个年纪类
public class Grade {
    /**
     * 年纪编号
     */
    private int gradeId;
    /**
     * 年假名称
     */
    private String gradeName;

    public Grade() {
    }

    public Grade(int gradeId, String gradeName) {
        this.gradeId = gradeId;
        this.gradeName = gradeName;
    }

    /**
     * 获取
     * @return gradeId
     */
    public int getGradeId() {
        return gradeId;
    }

    /**
     * 设置
     * @param gradeId
     */
    public void setGradeId(int gradeId) {
        this.gradeId = gradeId;
    }

    /**
     * 获取
     * @return gradeName
     */
    public String getGradeName() {
        return gradeName;
    }

    /**
     * 设置
     * @param gradeName
     */
    public void setGradeName(String gradeName) {
        this.gradeName = gradeName;
    }
    @Override
    public String toString() {
        return "Grade{gradeId = " + gradeId + ", gradeName = " + gradeName + "}";
    }
}

数据库如下图:

3、将用户对象的所有操作抽取成接口

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author 
 * @date 2022-09-12 21:35:49
 * @version 1.0.0
 * @description 将年纪对象的所有操作抽取成接口
 * 实现对数据库的增删改查
 */

public interface GradeDao {
    /**
     * @description 查询班级信息
     * key为空查询所有班级信息
     * key有值,根据key值进行模糊查询
     * @author
     * @date 2022-09-09 11:41:14
     * @param key 进行模糊查询的关键字
     * @return {@link List< Grade>}
     */
     List<Grade> getALL(String key);
     /**
      * @description 添加数据
      * @author
      * @date 2022-09-09 11:41:18
      * @param grade 年纪对象
      * @return {@link int}
      */
     int insertGrade(Grade grade);
     /**
      * @description 修改数据
      * @author
      * @date 2022-09-09 11:41:23
      * @param grade 年纪对象
      * @return {@link int}
      */
     int updateGrade(Grade grade);
     /**
      * @description 删除数据
      * @author
      * @date 2022-09-09 11:41:26
      * @param gradeId 年纪ID
      * @return {@link int}
      */
     int deleteGrade(int gradeId);
}

4、由不同数据库的实现类分别实现接口实现类实现接口并继承数据库工具类

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author 齐孟伟
 * @date 2022-09-12 21:58:38
 * @version 1.0.0
 * @description 数据库的实现类分别实现接口
 */

public class GradeDaoImpl extends BaseDao implements GradeDao {
    /**
     * @description 查询班级信息
     * key为空查询所有班级信息
     * key有值,根据key值进行模糊查询
     * @author
     * @date 2022-09-09 11:41:14
     * @param key 进行模糊查询的关键字
     * @return {@link List< Grade>}
     */
    @Override
    public List<Grade> getALL(String key) {
        //sql语句
        String sql = "SELECT * FROM GRADE WHERE GRADENAME LIKE CONCAT('%',?,'%')";
        //将获取的key放进数组
        Object [] obj = {key};
        //处理返回结果
        ResultSet resultSet = this.select(sql,obj);
        //创建年纪对象
        Grade grade = null;
        //创建数组用来存储年纪对象
        List<Grade> gradeList = new ArrayList<>();
        try{
            //resultSet.next():判断返回结果是否有值
            while (resultSet.next()){
                grade = new Grade();
                //获取数据库表的内容,这里的1可以是获取到表的列名,1表示第一列,2,表是第二列要有顺序
                grade.setGradeId(resultSet.getInt(1));
                grade.setGradeName(resultSet.getString(2));

                gradeList.add(grade);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //关闭资源
            this.close(resultSet);
        }
        return gradeList;
    }
    /**
     * @description 添加数据
     * @author
     * @date 2022-09-09 11:41:18
     * @param grade 年纪对象
     * @return {@link int}
     */
    @Override
    public int insertGrade(Grade grade) {
        //sql语句
        String sql = "INSERT INTO GRADE(GRADEID, GRADENAME) VALUES (?,?)";
        //将对象的属性值添加到 数组中
        Object [] obj = {grade.getGradeId(),grade.getGradeName()};
        //调用 添加数据的方法
        return this.update(sql,obj);
    }
    /**
     * @description 修改数据
     * @author
     * @date 2022-09-09 11:41:23
     * @param grade 年纪对象
     * @return {@link int}
     */
    @Override
    public int updateGrade(Grade grade) {
        //sql语句
        String sql = "UPDATE GRADE SET GRADENAME = ? WHERE GRADEID = ?";
        //将对象的属性值添加到 数组中
        Object [] obj = {grade.getGradeName(),grade.getGradeId()};
        //调用 添加数据的方法
        return this.update(sql,obj);
    }
    /**
     * @description 删除数据
     * @author
     * @date 2022-09-09 11:41:26
     * @param gradeId 年纪ID
     * @return {@link int}
     */
    @Override
    public int deleteGrade(int gradeId) {
        //sql语句
        String sql = "DELETE FROM GRADE WHERE GRADEID = ?";
        //将对象的属性值添加到 数组中
        Object [] obj = {gradeId};
        //调用 添加数据的方法
        return this.update(sql,obj);
    }
}

5、将通用的操作(如打开、关闭连接等)封装到工具类数据库工具类

        对BaseDao:增、删、改的通用方法

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author
 * @date 2022-09-12 22:01:34
 * @version 1.0.0
 * @description 将通用的操作(如打开、关闭连接等)封装到工具类
 */

public class BaseDao {
    /**
     * 获取驱动
     */
    Connection connection = null;
    /**
     * 连接数据库并进行操作
     */
    PreparedStatement preparedStatement = null;
    /**
     * 处理返回结果
     */
    ResultSet resultSet = null;
    /**
     * @description 获取驱动
     * @author
     * @date 2022-09-09 11:50:58
     * @param
     * @return {@link Connection}
     */
    public Connection getConnection(){
        //根据指定的键获取对应的值
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        // 获取驱动
        String driver = dataSourceConfig.getProperty("driver");
        // 获取数据库地址
        String url = dataSourceConfig.getProperty("url");
        // 获取用户名
        String username = dataSourceConfig.getProperty("username");
        // 获取密码
        String password = dataSourceConfig.getProperty("password");

        try {
            //加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(url,username,password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return connection;
    }
    /**
     * @description 查询班级信息
     *      key为空查询所有班级信息
     *      key有值,根据key值进行模糊查询
     * @author
     * @date 2022-09-09 11:54:58
     * @param sql sql语句
     * @param obj key值
     * @return {@link ResultSet}
     */
    public ResultSet select(String sql, Object[] obj){
        this.getConnection();
        try {
            preparedStatement = connection.prepareStatement(sql);
            //若传过来obj不为空,则解析参数集合
            if (obj != null && obj.length > 0){
                for (int i = 0; i < obj.length; i++) {
                    //对问号传参
                    preparedStatement.setObject((i + 1),obj[i]);
                }
            }
            resultSet = preparedStatement.executeQuery();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return resultSet;
    }
    /**
     * @description 对数据进行添加修改删除
     * @author
     * @date 2022-09-09 11:57:54
     * @param sql sql语句
     * @param obj key值
     * @return {@link int}
     */
    public int update(String sql, Object[] obj){
        //
        this.getConnection();
        int count = 0;
        try {
            preparedStatement = connection.prepareStatement(sql);
            if (obj != null && obj.length > 0){
                for (int i = 0; i < obj.length; i++) {
                    preparedStatement.setObject((i + 1),obj [i]);
                }
            }
            count = preparedStatement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            close(resultSet);
        }
        return count;
    }
    /**
     * @description 关闭资源
     * @author
     * @date 2022-09-12 22:00:57
     * @param res 
     * @return
     */
    public void close(ResultSet res){
        try {
            if (res != null){
                res.close();
            }
            if (resultSet != null){
                resultSet.close();
            }
            if (preparedStatement != null){
                preparedStatement.close();
            }
            if (connection != null){
                connection.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

6、在测试类进行测试

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author 齐孟伟
 * @date 2022-09-12 22:20:56
 * @version 1.0.0
 * @description 测试类
 */

public class SchoolSystemApplication {
    public static void main(String[] args) {
        GradeDao gradeDao = new GradeDaoImpl();
        /**
         * 查询
         */
        select("",gradeDao);
        /**
         * 添加数据
         */
        Grade grade = new Grade(6,"第六阶段");
        gradeDao.insertGrade(grade);
        select("",gradeDao);
        /**
         * 修改数据
         */
        // 获取所有的对象
        List<Grade> gradeList = gradeDao.getALL("");
        // 遍历数组
        for (int i = 0; i < gradeList.size(); i++) {
            if (gradeList.get(i).getGradeId() == 6){
                int gradeId = gradeList.get(i).getGradeId();
                String gradeName = "高三";
                Grade grade1 = new Grade(gradeId,gradeName);
                gradeDao.updateGrade(grade1);
            }
        }
        select("",gradeDao);
        /**
         * 删除数据
         */
        gradeDao.deleteGrade(6);
        select("",gradeDao);
    }
    /**
     * @description 遍历集合里的信息
     * @author
     * @date 2022-09-12 22:21:10
     * @param key key值
     * @param gradeDao
     * @return
     */
    public static void select(String key,GradeDao gradeDao){
        List<Grade> gradeList = gradeDao.getALL(key);
        for (int i = 0; i < gradeList.size(); i++) {
            System.out.println(gradeList.get(i).toString());
        }
        System.out.println("______________________");
    }
}

 7、单例模式

 Java中提供了Properties类来读取配置文件

方法名说明

void load(InputStream inStream)

通过输入流对指定文件进行装载,获取该文件中所有键-值对。

String getProperty(String key)

用指定的键在此属性列表中搜索属性。通过参数key得到其所对应的值。

读取配置文件,单独放在一个utils包里

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author
 * @date 2022-09-10 10:47:31
 * @version 1.0.0
 * @description 数据库配置类---读取数据库连接配置
 */

public class DataSourceConfig {
    /**
     * 以类名声明的此类对象
     */
    private static DataSourceConfig dataSourceConfig = null;
    
    Properties properties = null;
    /**
     * @description
     * @author
     * @date 2022-09-10 10:48:02
     * @param
     * @return {@link null}
     */
    public DataSourceConfig(){
        properties = new Properties();
        //配置文件路径
        String configFile = "database.properties";
        //加载配置文件到输入流
        InputStream inputStream = DataSourceConfig.class.getClassLoader().getResourceAsStream(configFile);
        try {
            //从输入流中读取属性列表
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * @description DataSourceConfig判定是否已经被创建
     * 如果创建过,直接返回
     * 如果没有,创建后返回
     * @author
     * @date 2022-09-10 10:45:49
     * @param
     * @return {@link DataSourceConfig}
     */
    public synchronized static DataSourceConfig getInstance(){
        if (dataSourceConfig == null){
            dataSourceConfig = new DataSourceConfig();
        }
        return dataSourceConfig;
    }
    /**
     * @description Properties对象根据传递的key值返回对应的value值
     * @author
     * @date 2022-09-10 10:45:55
     * @param key
     * @return {@link String}
     */
    public String getProperty(String key){

        String value = properties.getProperty(key);
        return value;
    }
}

读取配置文件,把获取驱动部分改为以下代码即可

/**
     * @description 获取驱动
     * @author 
     * @date 2022-09-10 10:52:34
     * @param
     * @return {@link Connection}
     */
    public Connection getConnection(){
        //根据指定的键获取对应的值
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        String driver = dataSourceConfig.getProperty("driver");
        String url = dataSourceConfig.getProperty("url");
        String username = dataSourceConfig.getProperty("username");
        String password = dataSourceConfig.getProperty("password");

        try {
            //加载驱动
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection(url,username,password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return connection;
    }

此模式称为单例模式:系统运行期间,有且仅有一个实例

1、它必须自行创建这个实例

2、定义了静态的该类私有对象

3、一个类只有一个实例——最基本的要求

4、只提供私有构造器

5、它必须自行向整个系统提供这个实例

6、提供一个静态的公有方法,返回创建或者获取本身的静态私有对象

懒汉模式:在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例。

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author
 * @date 2022-09-17 16:43:22
 * @version 1.0.0
 * @description 懒汉模式:在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例。
 */

public class DataScoreConfig {
    /**
     * DataSourceConfig类的声明
     */
    private static DataScoreConfig dataScoreConfig = null;
    /**
     * Properties类的文件处理引用
     */
    Properties properties = null;
    /**
     * @description 私有话构造方法
     * @author
     * @date 2022-09-17 16:53:13
     * @param
     * @return {@link null}
     */
    public DataScoreConfig(){
        properties = new Properties();
        String configFile = "database.properties";
        InputStream inputStream = DataScoreConfig.class.getClassLoader().getResourceAsStream(configFile);
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * @description
     * 查看dataSourceConfig是否为空
     * 为空则重新创建引用
     * 不为空直接返回
     * @author
     * @date 2022-09-17 16:53:05
     * @param
     * @return {@link DataScoreConfig}
     */
    public static synchronized DataScoreConfig getInstance(){
        if (dataScoreConfig == null){
            dataScoreConfig = new DataScoreConfig();
        }
        return dataScoreConfig;
    }
    /**
     * @description
     * 通过properties对象的getProperty方法
     * 获取database.properties文件中的对应可以的值
     * @author
     * @date 2022-09-17 16:53:01
     * @param key
     * @return {@link String}
     */
    public String getProperty(String key){
        String value = properties.getProperty(key);
        return value;
    }

饿汉模式:在类加载的时候,就完成初始化

/**
 * @authorDesc 乾坤未定, 你我皆是黑马.乾坤已定, 那就扭转乾坤
 * @author
 * @date 2022-09-17 16:43:22
 * @version 1.0.0
 * @description 饿汉模式:在类加载的时候,就完成初始化
 */

public class DataScoreConfig {
    /**
     * DataSourceConfig类的声明
     */
    private static DataScoreConfig dataScoreConfig = new DataScoreConfig;
    /**
     * Properties类的文件处理引用
     */
    Properties properties = null;
    /**
     * @description 私有话构造方法
     * @author
     * @date 2022-09-17 16:53:13
     * @param
     * @return {@link null}
     */
    public DataScoreConfig(){
        properties = new Properties();
        String configFile = "database.properties";
        InputStream inputStream =                                     
         DataScoreConfig.class.getClassLoader().getResourceAsStream(configFile);
        try {
            properties.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * @description
     * 查看dataSourceConfig是否为空
     * 为空则重新创建引用
     * 不为空直接返回
     * @author
     * @date 2022-09-17 16:53:05
     * @param
     * @return {@link DataScoreConfig}
     */
    public static DataScoreConfig getInstance(){
        return dataScoreConfig;
    }
    /**
     * @description
     * 通过properties对象的getProperty方法
     * 获取database.properties文件中的对应可以的值
     * @author
     * @date 2022-09-17 16:53:01
     * @param key
     * @return {@link String}
     */
    public String getProperty(String key){
        String value = properties.getProperty(key);
        return value;
    }

注意: 在整个程序运行期间,有且仅有一个实例。若违背这一点,所设计的类就不是单例类

单例模式懒汉模式饿汉模式
概念

在类加载时不创建实例,采用延迟加载的方式,在运行调用时创建实例

在类加载的时候,就完成初始化

特点

类加载速度快,但是运行时获取对象的速度较慢——时间换空间

类加载较慢,但获取对象速度快——空间换时间

延迟加载

具备

不具备

线程安全

线程不安全,解决方法使用同步(synchronized

线程安全

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用Java JDBC封装数据库事务的代码示例: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class TransactionExample { private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase"; private static final String DB_USER = "root"; private static final String DB_PASSWORD = "password"; public static void main(String[] args) { Connection connection = null; Statement statement = null; try { // Establish database connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); // Turn off auto-commit mode connection.setAutoCommit(false); // Execute SQL statements within a transaction statement = connection.createStatement(); statement.executeUpdate("INSERT INTO users (username, password) VALUES ('user1', 'pass1')"); statement.executeUpdate("INSERT INTO users (username, password) VALUES ('user2', 'pass2')"); // Commit transaction connection.commit(); System.out.println("Transaction completed successfully."); } catch (SQLException e) { // Rollback transaction in case of errors try { if (connection != null) { connection.rollback(); System.out.println("Transaction rolled back."); } } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); } finally { // Close resources try { if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } ``` 在上面的代码中,我们首先建立了一个数据库连接,然后通过调用 `setAutoCommit(false)` 方法来关闭自动提交模式,这样将使所有的 SQL 语句在一个事务中执行。接下来,我们执行了两个 SQL 语句来插入两条用户记录。如果这些语句都执行成功,我们将调用 `commit()` 方法来提交事务。如果在执行 SQL 语句时出现错误,我们将调用 `rollback()` 方法来回滚事务。最后,我们关闭了所有的数据库连接和语句对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值