• 练习项目三(图书馆管理系统)连接数据库------通用查询和通用增删改(底层实现)


    理论和实践的结合-----JavaSE实践项目

    实践项目三: 图书馆管理系统(合作重构版)
    【项目前提】

    掌握java基本语法
    熟悉使用流程控制
    理解面向对象思想
    熟练封装,继承,多态
    熟悉使用接口,异常
    熟悉使用集合
    熟悉掌握I/o流相关操作
    熟悉数据库操作
    了解三层架构和常用设计模式
    熟悉使用Git工具

    【项目说明】

    1.长期以来,人们使用传统的人工方式管理图书馆的日常业务,其操作流程比较烦琐。在借书时,读者首先将要借的书和借阅证交给工作人员,然后工作人员将每本书的信息卡片和读者的借阅证放在一个小格栏里,最后在借阅证和每本书贴的借阅条上填写借阅信息。在还书时,读者首先将要还的书交给工作人员,工作人员根据图书信息找到相应的书卡和借阅证,并填好相应的还书信息。太过于繁琐了!所以,我们需求设计一个图书管理系统来方便学生的借书和图书馆管理书籍。
    2.本系统在项目3基础上进行重构操作,调整了基本流程,增加了管理员和操作员不同角色的操作图书馆的功能。
    3.本系统首先需要进行登录或者注册,根据不同身份操作不同的功能。
    4.管理员主要负责对操作员的基本信息管理和相关逾期金额的设定和查看。
    5.操作员主要负责对读者的信息进行管理和相关图书进行管理。
    6.本项目还会利于数据库进行数据的读取和存储。

    项目功能流程结构图:

    在这里插入图片描述

    在练习项目三图书馆管理系统时,所有的数据操作基本就是增删改查,我一开始使用的是手动敲底层的增删改查,敲了两个模块的增删改查后发现代码量重复的操作其实非常多,每一个增删改操作就会多了个方法,但实际核心不同的也就sql语句。

    部分手敲底层sql方法:

    /**
         * 判断用户名和密码是否存在在Operator数据库表中
         * @param name
         * @return true存在 false不存在
         */
        public Boolean queryOperatorByNameAndPassword(String name, String password){
            boolean existsFlag = false;
            Connection connection=null;
            Operator operator=null;
            try {
                QueryRunner runner = new QueryRunner();
                connection = JDBCUtils.getConnection();
                String sql="select name,password from operator where name=? and password=? ";
                BeanHandler<Operator> handler = new BeanHandler<>(Operator.class);
                operator = runner.query(connection, sql, handler, name,password);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                JDBCUtils.closeResource(connection,null,null);
            }
            if (operator!=null){
                existsFlag=true;
            }
            return existsFlag;
        }
    
        /**
         * 判断用户名是否存在在Operator数据库表中
         * @param name
         * @return  true存在 false不存在
         */
        public boolean queryOperatorByName(String name){
            boolean existsFlag = false;
            Connection connection=null;
            Operator operator=null;
            try {
                QueryRunner runner = new QueryRunner();
                connection = JDBCUtils.getConnection();
                String sql="select name from operator where name=?  ";
                BeanHandler<Operator> handler = new BeanHandler<>(Operator.class);
                operator = runner.query(connection, sql, handler, name);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                JDBCUtils.closeResource(connection,null,null);
            }
            if (operator!=null){
                existsFlag=true;
            }
            return existsFlag;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    其实仔细看针对查询的数据库语句时,核心不同的就select语句,而我却写了这么多重复代码。大大的增强了代码冗余度。这样一来,不同的表就有不同的增删改查方法,就核心sql的语句不同而已,却多出很多代码量。
    下面就交出我的通用表的通用查询和通用增删改查。

    /**
       * 增删改通用方法
       */
      public int update(String sql,Object...args) {
          Connection connection=null;
          PreparedStatement ps=null;
          try{
              //1.获取数据库连接
              connection = JDBCUtils.getConnection();
              //2.预编译sql语句,返回preparedStatement实例对象
              ps = connection.prepareStatement(sql);
              //3.填充占位符
              for (int i=0;i<args.length;i++){
                  ps.setObject(i+1,args[i]);
              }
              //4.执行
              return ps.executeUpdate();
          }catch (Exception e){
              e.printStackTrace();
          }finally {
              //5.关闭资源
              JDBCUtils.closeResource(connection,null,ps);
          }
          return 0;
      }
    
      /**
       * 通用表通用查询返回一个集合
       * @param clazz 查询实体类
       * @param sql 查询语句
       * @param args 查询字段
       * @param <T>
       * @return 数据集合
       */
      public  <T> List<T> getForList(Class<T> clazz, String sql, Object...args){
          Connection connection = null;
          PreparedStatement ps = null;
          ResultSet resultSet = null;
    
          try {
              connection = JDBCUtils.getConnection();
              ps = connection.prepareStatement(sql);
              for (int i = 0; i < args.length; i++) {
                  ps.setObject(i + 1, args[i]);
              }
              //执行,获取结果集
              resultSet = ps.executeQuery();
              ResultSetMetaData metaData = resultSet.getMetaData();
              //通过结果集获取元数据再获取列的个数
              int columnCount = metaData.getColumnCount();
    
              ArrayList<T> list = new ArrayList<>();
              while (resultSet.next()) {
                  //创建实体类对象
                  T t = clazz.newInstance();
                  for (int i = 0; i < columnCount; i++) {
                      //通过ResultSet获取每个列的列值
                      Object columnValue = resultSet.getObject(i + 1);
                      //通过ResultSetMetaData获取每个列的列名,当数据库表中的列名和java中类中的属性名不一样时会报错
                      //解决方法就是获取列的别名
                      // String columnName = metaData.getColumnName(i+1);
                      String columnLabel = metaData.getColumnLabel(i + 1);
                      //通过反射将对象指定名columnLabel的属性赋值为指定的值columnValue
                      Field declaredField = clazz.getDeclaredField(columnLabel);
                      declaredField.setAccessible(true);
                      declaredField.set(t, columnValue);
    
                  }
                  list.add(t);
              }
              return list;
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              JDBCUtils.closeResource(connection, resultSet,ps );
          }
          return null;
      }
    
    
    
      /**
       * 通用所有表的通用查询
       * @param clazz 需要查询的实体类类名
       * @param sql 查询语句
       * @param args 要查询的列
       * @param <T> 泛型
       * @return 一个实体类对象
       */
      public <T> T getInstance(Class<T> clazz, String sql, Object... args) {
          Connection connection = null;
          PreparedStatement ps = null;
          ResultSet resultSet = null;
    
          try {
              connection = JDBCUtils.getConnection();
              ps = connection.prepareStatement(sql);
              for (int i = 0; i < args.length; i++) {
                  ps.setObject(i + 1, args[i]);
              }
              //执行,获取结果集
              resultSet = ps.executeQuery();
              ResultSetMetaData metaData = resultSet.getMetaData();
              //通过结果集获取元数据再获取列的个数
              int columnCount = metaData.getColumnCount();
    
              if (resultSet.next()) {
                  //创建实体类对象
                  T t = clazz.newInstance();
                  for (int i = 0; i < columnCount; i++) {
                      //通过ResultSet获取每个列的列值
                      Object columnValue = resultSet.getObject(i + 1);
                      //通过ResultSetMetaData获取每个列的列名,当数据库表中的列名和java中类中的属性名不一样时会报错
                      //解决方法就是获取列的别名
                      // String columnName = metaData.getColumnName(i+1);
                      String columnLabel = metaData.getColumnLabel(i + 1);
                      //通过反射将对象指定名columnLabel的属性赋值为指定的值columnValue
                      Field declaredField = clazz.getDeclaredField(columnLabel);
                      declaredField.setAccessible(true);
                      declaredField.set(t, columnValue);
    
                  }
                  return t;
              }
          } catch (Exception e) {
              e.printStackTrace();
          } finally {
              JDBCUtils.closeResource(connection, resultSet, ps);
          }
    
          return null;
      }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133

    这样一来不同的表就针对增删改就传入实体类的反射和占位符变量就好了,针对查询就传入实体类的反射和sql语句和占位符变量就好了。就让这些数据库数据操作类继承这个通用增删改查类。
    以下改变后的操作数据库增删改查dao类:

     /**
       * 获取指定图书类别的图书集合
       * @param readerType
       * @return BookListByBookType
       */
      public List<Reader> geReaderListByReaderType(String readerType){
          String sql="select reader_number readerNumber,type_number typeNumber," +
                  "reader_type readerType,name,age,sex,phone,department," +
                  "record_date recordDate FROM reader WHERE reader_type=?";
          return getForList(Reader.class, sql, readerType);
      }
    
      /**
       * 通过readerNUmber获取该读者对象
       * @param readerNumber
       * @return reader
       */
      public Reader geReaderByReaderNumber(int readerNumber){
          String sql="select reader_number readerNumber,type_number typeNumber," +
                  "reader_type readerType,name,age,sex,phone,department," +
                  "record_date recordDate FROM reader WHERE reader_number=?";
          return getInstance(Reader.class,sql,readerNumber);
      }
       /**
       * 插入一个新读者对象到数据库中
       * @param reader
       * @return true成功 ,false失败
       */
      public boolean insertReader(Reader reader){
          String sql = "insert into reader (type_number,reader_type,name,age,sex,phone,department,record_date) values (?,?,?,?,?,?,?,?)";
          int update = update(sql,reader.getTypeNumber(),reader.getReaderType(), reader.getName(),
                  reader.getAge(),reader.getSex(),reader.getPhone(),reader.getDepartment(),reader.getRecordDate());
          if (update>0){
              return true;
          }else {
              return false;
          }
      }
    
      /**
       * 更新一个读者对象到数据库中
       * @param reader
       * @return true成功 ,false失败
       */
      public boolean updateReader(Reader reader) {
          String sql = "update reader set type_number=?,reader_type=?,name=?,age=?," +
                  "sex=?,phone=?,department=?,record_date=? where reader_number=?";
          int update = update(sql, reader.getTypeNumber(),reader.getReaderType(), reader.getName(),
                  reader.getAge(),reader.getSex(),reader.getPhone(),reader.getDepartment(),reader.getRecordDate(),reader.getReaderNumber());
          if (update > 0) {
              return true;
          } else {
              return false;
          }
      }
    
      /**
       * 根据readerNumber删除指定读者
       *
       * @param readerNumber
       * @return true删除成功,false删除失败
       */
      public boolean delReader(int readerNumber) {
          String sql = "delete from reader where reader_number=?";
          int update = update(sql, readerNumber);
          if (update > 0) {
              return true;
          } else {
              return false;
          }
      }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    这样就简洁了太多了!只需要编写不同的sql语句再调用父类的通用增删改查方法就行了。

  • 相关阅读:
    CSP - J day8
    Proximal Policy Optimization Algorithms
    以变化的角度看待 dpdk 中向量收发包函数的限制
    python爬虫采集企查查数据
    【架构设计】作为架构师你应该掌握的画图技术
    ARMv8内存模型
    手搭手Ajax实现搜索地址自动补全功能
    车间调度|基于帝王蝶优化算法的车间调度(Matlab代码实现)
    计算机毕业设计选题推荐-公共浴池微信小程序/安卓APP-项目实战
    PSD95抗体研究丨SYSY PSD95抗体结果图展示
  • 原文地址:https://blog.csdn.net/qq_45043813/article/details/125526821