欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

《架构探险》之数据访问层代码优化

程序员文章站 2022-06-13 21:42:54
...

        写代码应该是一个由繁到简,然后由简到繁的一个螺旋上升的过程。

 

        没钱就应该多读电子书,最近看了看《架构探险》,写点东西标记一下~

        在看服务层代码优化那部分时,我想起了在本科实训时写的代码,很久很久以前,在一个民风淳朴的实训基地...

        访问数据库的代码是这个样子:

1、首先是配置文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mytest
jdbc.username=mzuser
jdbc.password=123456

 2、然后是在Dao类中加载初始化(主要是逻辑):

static{
     conf = loadProperties("config.properties");
     driver = getDriver(conf);
     url = getURL(conf);
     userName = getUserName(conf);
     password = getPassword(conf);

     Class.forName(driver);    //省略try
}

 3、万事俱备只欠东风,访问数据(举个例子):

public List<Customer> getCustomerList(){
     try{
     customers = new ArrayList<Customer>();
     sql = "";
     conn = DriverManager.getConnection(url,username,password);
     preparedStatement = conn.prepareStatement(sql);
     resultSet = preparedStatement.executeQuery();
     while(resultSet.next()){
         customer = new Customer();
         set...
         customers.add(customer);
     }
     return customers;
     }catch(SQLExeption e){

     }finally{
         try{
              conn.close()
         }catch(...){
         }
     }
}

 接下来应该就是很开心的不断的写类似的代码......

        但是,当随着业务不断的增长,访问数据库的代码越来越多,你会发现有很多重复的代码,如上面的初始化和获取连接,相当于搭台子唱戏,每次都需要搭一个样的台子,既然这样为什么不先搭好台子,管他是哪个戏班子。

       于是...

        1、可以有一个工具类如DataBaseHelper来负责统一加载参数,然后将获取连接和关闭连接的代码封装成方法;

        2、为了避免多线程的不安全,可以用ThreadLocal来隔离连接;

        3、可以使用数据库连接池来统一管理数据库连接,如使用BasicDataSource

 

private static final BasicDataSource DATA_SOURCE;

private static final ThreadLocal<Connection> CONNECTION_HOLDER = new ThreadLocal<Connection>();

static {
    Properties conf = PropsUtil.loadProps("config.properties");
    String driver = conf.getProperty("jdbc.driver");
    String url = conf.getProperty("jdbc.url");
    String userName = conf.getProperty("jdbc.username");
    String password = conf.getProperty("jdbc.password");

    DATA_SOURCE = new BasicDataSource();
    DATA_SOURCE.setDriverClassName(driver);
    DATA_SOURCE.setUrl(url);
    DATA_SOURCE.setUsername(userName);
    DATA_SOURCE.setPassword(password);

}

/**
* get connection
*/
public static Connection getConnection(){
    Connection connection = CONNECTION_HOLDER.get();
    if(connection == null){
        try {
            connection = DATA_SOURCE.getConnection();
            CONNECTION_HOLDER.set(connection);
        }catch (SQLException e){
            LOGGER.error("execute sql error", e);
        }
    }

    return connection;
}

        据说DbUtils提供的QueryRunner对象可以面向实体进行查询,就像这样子:

/**
* select list
*/
public static <T> List<T> queryEntityList(Class<T> entityClass, String sql, Object... params){
    List<T> entityList = new ArrayList<T>();
    Connection connection = null;
    try {
        connection = getConnection();
        entityList = QUERY_RUNNER.query(connection, sql, new BeanListHandler<T>(entityClass), params);
    }catch (SQLException e){
        LOGGER.error("query error", e);
    }
    return entityList;
}

        现在访问数据库就简单了:

public List<Customer> getCustomer(){
    String sql = "select * from customer";
    return DatabaseHelper.queryEntityList(Customer.class, sql);
}

         看起来还不错,至少Dao层不会一个个都像穿了大棉袄似得那么厚厚的~