簡(jiǎn)易JDBC框架實(shí)現(xiàn)過程詳解

1 準(zhǔn)備

專注于為中小企業(yè)提供做網(wǎng)站、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)梁山免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了數(shù)千家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

  • JDBC 基本知識(shí)
  • JDBC元數(shù)據(jù)知識(shí)
  • 反射基本知識(shí)

2: 兩個(gè)問題

業(yè)務(wù)背景:系統(tǒng)中所有實(shí)體對(duì)象都涉及到基本的CRUD操作。所有實(shí)體的CUD操作代碼基本相同,僅僅是發(fā)送給數(shù)據(jù)庫的sql語句不同而已,因此可以把CUD操作的所有相同代碼抽取到工具類的一個(gè)update方法中,并定義參數(shù)接收變化的sql語句。

實(shí)體的R操作,除sql語句不同之外,根據(jù)操作的實(shí)體不同,對(duì)ResultSet的映射也各不相同,因此可定義一個(gè)query方法,除以參數(shù)形式接收變化的sql語句外,可以使用策略模式由query方法的調(diào)用者決定如何把ResultSet中的數(shù)據(jù)映射到實(shí)體對(duì)象中。

3: JDBC 封裝 update query方法

public class JdbcNewUtils {
  private JdbcNewUtils() {}
  /**
   * 這里可以使用properties進(jìn)行替換
   */
  private static final String USER = "root";
  private static final String PWD = "root";
  private static final String URL = "jdbc:MySQL://127.0.0.1:3306/day?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&generateSimpleParameterMetadata=true";
  private static final String DRIVER= "com.mysql.jdbc.Driver";
  static {
    try {
      Class.forName(DRIVER);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
  
  public static Connection getConnection() throws SQLException {
    Connection connection = DriverManager.getConnection(URL, USER, PWD);
    return connection;
  }
  /**
   * CUD 返回影響數(shù)目
   * @param sql
   * @param args
   * @return int
   */
  public static int update(String sql,Object [] args) {
    PreparedStatement ps = null;
    Connection conn = null;
    try {
      conn=getConnection();
      ps = conn.prepareStatement(sql);
      for (int i = 1; i <= args.length; i++) {
        ps.setObject(i, args[i-1]);
      }
      return ps.executeUpdate();
    } catch (SQLException e) {
      e.printStackTrace();
    }finally {
      close(conn, ps);
    }
    return 0;
  }
  /**
   * 查詢結(jié)果封裝Bean
   * @param sql
   * @param args
   * @param rsh
   * @return Object
   */
  public static Object query(String sql,Object [] args,ResultSetHandler rsh) {
    PreparedStatement ps = null;
    Connection conn = null;
    try {
      conn=getConnection();
      ps = conn.prepareStatement(sql);
      for (int i = 0; i < args.length; i++) {
        ps.setObject(i+1, args[i]);
      }
      return rsh.handle(ps.executeQuery());
    } catch (SQLException e) {
      e.printStackTrace();
    }finally {
      close(conn, ps);
    }
    return null;
  }
  
  /**
  * 關(guān)閉所有打開的資源
  */
  public static void close(Connection conn, Statement stmt) {
    if(stmt!=null) {
      try {
        stmt.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    if(conn!=null) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
  /**
  * 關(guān)閉所有打開的資源
  */
  public static void close(Connection conn, Statement stmt, ResultSet rs) {
    if(rs!=null) {
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
    close(conn, stmt);
  }

}

4: query

每次查詢根據(jù)查詢的參數(shù)不同, 返回的ResultSet 也不同, 這個(gè)規(guī)則我們需要單獨(dú)編寫規(guī)則解析器, 這里用到了策略設(shè)計(jì)模式,

將ResultSetHandler 定義解決問題的接口, handle為那些需要實(shí)現(xiàn)的具體解決的辦法

public interface ResultSetHandler {
  Object handle(ResultSet resultSet);
}

下面我實(shí)現(xiàn)了Beanhandler 和 BeanListHandler 分別是 單個(gè)的Bean 和一個(gè)列表的Bean

package jdbc.simpleframwork;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;

public class BeanHandler implements ResultSetHandler {

  private Class<?> obj;
  public BeanHandler(Class<?> obj) {
    this.obj = obj;
  }
  @Override
  public Object handle(ResultSet resultSet){
    try {
      if(!resultSet.next()) {
        return null;
      }
      Object instance = obj.newInstance();
      ResultSetMetaData metaData = resultSet.getMetaData();
      int count = metaData.getColumnCount();
      for(int i=1;i<=count;i++) {
        Field f = obj.getDeclaredField(metaData.getColumnName(i));
        f.setAccessible(true);
        f.set(instance, resultSet.getObject(i));
      }
      return instance;
    } catch (InstantiationException | IllegalAccessException e) {
      e.printStackTrace();
    } catch (SQLException e) {
      e.printStackTrace();
    } catch (NoSuchFieldException e) {
      e.printStackTrace();
    } catch (SecurityException e) {
      e.printStackTrace();
    }
    return null;
  }
}
package jdbc.simpleframwork;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;

public class BeanListHandler implements ResultSetHandler {

  private Class<?> clazz;

  public BeanListHandler(Class<?> clazz) {
    super();
    this.clazz = clazz;
  }

  @Override
  public Object handle(ResultSet resultSet) {
    try {
      ArrayList<Object> objlist = new ArrayList<>();
      ResultSetMetaData metaData = resultSet.getMetaData();
      int count = metaData.getColumnCount();
      while (resultSet.next()) {
        Object instace = clazz.newInstance();
        for (int i = 0; i < count; i++) {
          Field f = clazz.getDeclaredField(metaData.getColumnName(i + 1));
          f.setAccessible(true);
          f.set(instace, resultSet.getObject(i + 1));
          f.setAccessible(false);
        }
        objlist.add(instace);

      }
      return objlist;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
}

5 測(cè)試

public class TestFramwork {

  public static void main(String[] args) throws SQLException {
    Connection conn = JdbcNewUtils.getConnection();

    String sql = "select * from student where id=?";
    PreparedStatement ps = conn.prepareStatement(sql);
    Student stu = (Student) JdbcNewUtils.query(sql, new Object[] { 1 }, new BeanHandler(Student.class));
    System.out.println(stu);

    String sql2 = "select * from student";
    ArrayList<Student> list = (ArrayList<Student>) JdbcNewUtils.query(sql2, new Object[] {},
        new BeanListHandler(Student.class));
    System.out.println(list);
  }

}

6: 總結(jié)

Update系列操作:

對(duì)于CUD操作,SQL只有站位符號(hào)的多少發(fā)生了改變,對(duì)于傳遞參數(shù)才是我們需要關(guān)注的地方,但是JDBC提供了一系列傳遞參數(shù)解析的辦法,通過set系列函數(shù),將參數(shù)值傳遞進(jìn)行,所以我們只需要封裝一個(gè)通用的update即可
Query系列操作

對(duì)R操作,就復(fù)雜得多,SQL語句的不同,返回的ResultSet也不同,可以單個(gè)Bean 或者一個(gè)List,一個(gè)Map等,可以看出來,實(shí)際上很多框架提供的也就是這些方法的封裝

對(duì)了 真正應(yīng)用上 我們的DAO 一邊是 下面的寫法

public class AccountDao {
  public void add(Account account) throws SQLException{
    String sql = "insert into account(name , money) values(?, ?)";
    Object[] params = {account.getName(), account.getMoney()};
    JdbcUtils.update(sql, params);
  }
  
  public void delete(int id ) throws SQLException{
    String sql = "delete from account where id = ?";
    Object[] params = {id};
    JdbcUtils.update(sql, params);
  }
  
  public void update(Account account) throws SQLException{
    String sql = "update account set name = ?, money = ? where id = ?";
    Object params[] = {account.getName(), account.getMoney(), account.getId()};
    JdbcUtils.update(sql, params);
  }
  
  public Account find(int id ) throws SQLException{
    String sql = "select * from account where id = ?";
    Object params[] = {id};
    return (Account) JdbcUtils.query(sql, params, new BeanHandler(Account.class));
  }
  
  public List getAll() throws SQLException{
    String sql = "select * from account";
    Object params[] = {};
    return (List)JdbcUtils.query(sql, params, new BeanListHandler(Account.class));
  }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。

分享名稱:簡(jiǎn)易JDBC框架實(shí)現(xiàn)過程詳解
網(wǎng)站URL:http://muchs.cn/article34/ijdspe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、網(wǎng)站設(shè)計(jì)、靜態(tài)網(wǎng)站、營(yíng)銷型網(wǎng)站建設(shè)、商城網(wǎng)站手機(jī)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

綿陽服務(wù)器托管