JDBC

JDBC

背景

我们的应用都是动态运行的,最早就是用于复杂计算领域,你给应用一些入参,应用通过一系列的复杂计算,最终得到结果,返回给使用者。现在的应用也一样,只不过支持的领域比较广,业务更复杂而已。我们都知道应用是需要加载到内存,才能运行。这样的话,当关闭进程,所有的数据都会丢失。所以为了保存数据,出现了数据库技术--主要用于存储数据。

数据库介绍

数据库是“按照数据结构来组织、存储和管理数据的仓库”。是一个长期存储在计算机内的、有组织的、可共享的、统一管理的大量数据的集合。

数据库技术的出现解决了应用数据的存储问题,但随着时间的推移,越来越多的数据库技术出现,例如Oracle、mysql、SqlServer等等,数据库种类变多是一种好的现象,可以让程序员有了跟多的选择,但存在一个问题,他们对外提供的接口各不相同,程序员要想使用不同的数据库,就需要了解对应操作数据库的API,这样就增加了程序员的学习成本,所以作为当时业界老大的SUN公司,就出了一套java语言操作数据库的标准(JDBC)。

jdbc历史背景

这样的好处有哪些?

  • JAVA代码中不会再出现具体某种数据库相关的api,全部面向JDBC规范编程。

  • 减轻程序员的学习成本,只需要学习JDBC相关的接口,无需关心底层的具体实现

  • 更容易替换数据库

JDBC简介

Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。

JDBC标准相关的类在java.sql包以及扩展包javax.sql包下

核心类作用
DriverManager注册驱动,获取Connection
Connection表示一个数据库连接,可以获取Statement对象
Statement向数据库发送SQL语句
ResultSet结果集,是一个二维表格

 

使用JDBC操作数据库

示例说明:我们使用典型的web架构的3层架构(表示层、业务逻辑层、数据持久层),这里主要关心的是数据持久层,所以只实现了后面两层。模拟从数据库student表中查询年龄大于18岁的学生。

  • 源码仓库

  • 分支study/mybatis-3.5.6

  • 具体请参考readme文档

DbPropertiesManager类

  • 负责数据库相关属性(url、username、password)的管理

public class DbPropertiesManager{
  private static DbProperties dbProperties;
​
  public static DbProperties getDbProperties() throws IOException {
    if (dbProperties == null) {
      dbProperties = new DbProperties();
    }
    return dbProperties;
  }
​
  @Getter
  public static class DbProperties {
    private final String url;
    private final String username;
    private final String password;
​
    public DbProperties() throws IOException {
      InputStream is = ClassLoader.getSystemResourceAsStream("datasource.properties");
      Properties properties = new Properties();
      properties.load(is);
      url = properties.getProperty("url");
      username = properties.getProperty("username");
      password = properties.getProperty("password");
    }
  }
}

StudentService类

  • 模拟业务逻辑,调用dao层

public class StudentService {
  private final StudentDao studentDao;
​
  public StudentService() throws IOException {
    studentDao = new StudentDao();
  }
​
  public List<Student> getAgeGreaterThan(int minAge) {
    List<Student> studentList = studentDao.getAgeGreaterThan(minAge);
    return Optional.ofNullable(studentList).orElse(Collections.emptyList());
  }
}

StudentDao类

  • 操作数据库,给业务逻辑层反馈数据

public class StudentDao {
​
  private final DbPropertiesManager.DbProperties dbProperties;
​
  public StudentDao() throws IOException {
    dbProperties = DbPropertiesManager.getDbProperties();
  }
  public List<Student> getAgeGreaterThan(int minAge) {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
​
    List<Student> studentList = new ArrayList<>();
    try {
      //获取连接
      connection = DriverManager.getConnection(dbProperties.getUrl(), dbProperties.getUsername(), dbProperties.getPassword());
      //构造sql语句
      String sql = "SELECT * FROM student WHERE age > ?";
      //获取Statement对象
      statement = connection.prepareStatement(sql);
      //设置参数
      statement.setInt(1, minAge);
      //执行
      statement.execute();
      //获取结果集
      resultSet = statement.getResultSet();
      //处理结果集
      while (resultSet.next()) {
        int id = resultSet.getInt("id");
        String name = resultSet.getString("name");
        int age = resultSet.getInt("age");
        Student student = Student.builder()
          .id(id)
          .name(name)
          .age(age)
          .build();
        studentList.add(student);
      }
      //关闭资源
    }catch (SQLException e) {
      e.printStackTrace();
    }finally {
      if (resultSet != null) {
        try {
          resultSet.close();
        }catch (SQLException e) {
          e.printStackTrace();
        }
      }
      if (statement != null) {
        try {
          statement.close();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
      if (connection != null) {
        try {
          connection.close();
        } catch (SQLException e) {
          e.printStackTrace();
        }
      }
    }
    return studentList;
  }
}

StudentServiceTest类

  • 测试类

class StudentServiceTest {
  @Test
  public void testGetAgeGreaterThan() throws IOException {
    StudentService service = new StudentService();
    List<Student> studentList = service.getAgeGreaterThan(18);
    Assertions.assertNotNull(studentList);
  }
}

运行结果

运行结果

存在的问题

通过上面一个示例的演示,可以通过JDBC从数据库中获取到我们想要的结果,但是仅仅是一个查询操作我们就写了很长的代码。操作数据库我们大致需要一下流程:

  1. 获取数据库连接(要操作数据库就需要与数据库建立连接)

  2. 构造要执行的sql语句(告诉数据库做什么操作CRUD,此时sql的一些参数可能还没有填充)

  3. 获取Statement对象

  4. 设置参数(对sql中的占位符进行替换)

  5. 执行(调用DBMS执行sql)

  6. 获取结果集

  7. 解析结果集(将返回的结果解析成预期的对象)

  8. 关闭资源(由于Connection、Statement、ResultSet都是一种资源,所以需要关闭)

一般我们dao层的类有很多对数据库的操作,而每一次对数据库的操作,我们都要写上面类似固定的流程,这就导致代码大量冗余,而作为程序员,最基本的要求就是去除冗余保证代码的可维护性、可读性。那我们分析一下整个流程有哪些是始终不变的,哪些是每次变化的?

不变的内容: 获取连接、获取Statement、执行sql、获取结果、解析结果、关闭资源

变化的内容:构造的sql语句、sql语句中的入参

总结

JDBC的作用主要为java访问数据库提供统一接口标准,使得java代码与具体数据库解耦。但通过分析我们发现使用原始JDBC操作数据库会有代码冗余问题,使得DAO层代码臃肿不好维护,接下来我们就来学习Mybatis作为对JDBC的一种封装,它如何解决上面的问题的呢?

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值