開篇
本篇針對(duì)項(xiàng)目中的Server層進(jìn)行優(yōu)化介紹汤徽。先來看看Server層的目前情況。
image.png
可以看到由于業(yè)務(wù)簡單灸撰。只有一個(gè)Server類谒府。
以下是CustomerService類的靜態(tài)代碼塊
image.png
以下是CustomerService類的其中一個(gè)方法
image.png
缺點(diǎn):
- 將數(shù)據(jù)庫的加載是一個(gè)公共代碼塊,應(yīng)該提取出來浮毯,不應(yīng)該寫在某個(gè)類中完疫。
- Service 層是對(duì)業(yè)務(wù)邏輯的處理,但是在方法中债蓝,對(duì)查詢的結(jié)果進(jìn)行了大量的操作壳鹤。這樣使業(yè)務(wù)層的代碼太過渾濁。應(yīng)該講查詢結(jié)果的處理封裝起來饰迹。
代碼實(shí)現(xiàn)
將Server層的對(duì)數(shù)據(jù)庫操作的代碼提取出來
要求:
- 建立一個(gè)DatabaseUtil類 封裝對(duì)數(shù)據(jù)庫的加載
- 再創(chuàng)建兩個(gè)方法getConnection()獲取數(shù)據(jù)庫連接 和closeConnection() 關(guān)閉數(shù)據(jù)庫連接芳誓。
- 對(duì)數(shù)據(jù)庫操作的代碼實(shí)現(xiàn)封裝起來
實(shí)現(xiàn):
- 為了能更好地封裝JDBC的操作。這里還使用了Apache Common項(xiàng)目中的DbUtils類庫蹦锋,這個(gè)類庫可以更好地幫我處理數(shù)據(jù)庫數(shù)據(jù)兆沙。
- DatabaseUtil 類就實(shí)現(xiàn)了加載驅(qū)動(dòng)欧芽,獲取連接莉掂,和對(duì)數(shù)據(jù)庫進(jìn)行操作并對(duì)查詢結(jié)果進(jìn)行處理,然后結(jié)果給Server層的3個(gè)主要功能千扔。
代碼如下:
public class DatabaseUtil {
private static final String DRIVER;
private static final String URL;
private static final String USERNAME;
private static final String PASSWORD;
// 利用Apache的一個(gè)工具庫DbUtils 對(duì)JDBC的封裝
private static final QueryRunner QUERY_RUNNER = new QueryRunner();
private static final Logger logger = LoggerFactory.getLogger(DatabaseUtil.class);
static{
System.out.println("配置加載");
Properties conf = PropsUtil.loadProps("config.properties");
DRIVER = conf.getProperty("jdbc.driver");
URL = conf.getProperty("jdbc.url");
USERNAME = conf.getProperty("jdbc.username");
PASSWORD = conf.getProperty("jdbc.password");
//JDBC流程第一步 加載驅(qū)動(dòng)
try {
Class.forName(DRIVER);
} catch (ClassNotFoundException e) {
logger.error("加載jdbc驅(qū)動(dòng)失敗",e);
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return connection;
} catch (SQLException e) {
logger.error("獲取連接失敗",e);
e.printStackTrace();
}
return null;
}
public static void closeConnection(Connection connection) {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
logger.error("關(guān)閉連接失敗",e);
e.printStackTrace();
}
}
}
/**
* 查詢獲取實(shí)體列表
* @param entityClass 返回對(duì)象
* @param sql 查詢語句
* @param params 查詢條件
*
*
*/
public static <T> List<T> queryEntityList(Class<T> entityClass,String sql, Object... params) {
List<T> entityList = null;
Connection con = null;
try {
con = getConnection();
entityList =
QUERY_RUNNER.query(con, sql, new BeanListHandler<T>(entityClass), params);
} catch (SQLException e) {
logger.error("查詢失敗",e);
e.printStackTrace();
}finally {
closeConnection(con);
}
return entityList;
}
/**
* 查詢實(shí)體
* @param tClass
* @param sql
* @param params
* @param <T>
* @return
*/
public static <T> T queryEntity(Class<T> tClass, String sql, Object... params) {
T entity = null;
Connection con = null;
try {
con = getConnection();
entity =
QUERY_RUNNER.query(con, sql, new BeanHandler<T>(tClass), params);
} catch (SQLException e) {
logger.error("查詢失敗",e);
e.printStackTrace();
}finally {
closeConnection(con);
}
return entity;
}
/**
* 執(zhí)行查詢語句
* 返回一個(gè)List對(duì)象憎妙。Map 表示列名與列值得映射關(guān)系
* @param sql
* @param params
* @return
*/
public static List<Map<String, Object>> executeQuery(String sql, Object... params) {
List<Map<String,Object>> entity = null;
Connection con = null;
try {
con = getConnection();
entity =
QUERY_RUNNER.query(con, sql, new MapListHandler(), params);
} catch (SQLException e) {
logger.error("查詢失敗",e);
e.printStackTrace();
}finally {
closeConnection(con);
}
return entity;
}
/**
* 執(zhí)行更新語句(update,insert,delete)
* @param sql
* @param params
* @return
*/
public static int executeUpdate(String sql, Object... params) {
int rows=0;
Connection con = null;
try {
con = getConnection();
rows =
QUERY_RUNNER.update(con, sql, new MapListHandler(), params);
} catch (SQLException e) {
logger.error("查詢失敗",e);
e.printStackTrace();
}finally {
closeConnection(con);
}
return rows;
}
/**
* 插入實(shí)體
* @param entityClass
* @param filedMap
* @param <T>
* @return
*/
public static <T> boolean insertEntity(Class<T> entityClass, Map<String, Object> filedMap) {
/*
* 1. 判斷filedMap是否為空
* 2. 對(duì)Map遍歷,拼接sql語句
* 3. 執(zhí)行語句
* */
if (MapUtils.isEmpty(filedMap)) {
logger.error("插入實(shí)體失敗,實(shí)體Map為空");
return false;
}
Iterator<String> iterator = filedMap.keySet().iterator();
StringBuffer columns = new StringBuffer("(");
StringBuffer values = new StringBuffer("(");
String sql=("insert into" + entityClass.getSimpleName());
while (iterator.hasNext()) {
String key = iterator.next();
columns.append(key).append(", ");
values.append("?, ");
}
// 刪除最后一個(gè) , 然后加上 )
columns.replace(columns.lastIndexOf(", "), columns.length(), ")");
values.replace(values.lastIndexOf(", "), values.length(), ")");
sql += columns + " values " + values;
Object[] params = filedMap.values().toArray();
return executeUpdate(sql,params)==1;
}
public static <T> boolean updateEntity(Class<T> entityClass, long id, Map<String, Object> fieldMap) {
//TODO
return false;
}
public static <T> boolean deleteEntity(Class<T> entityClass, long id) {
String sql = "Delete From " + entityClass.getSimpleName() + " Where id = ?";
return executeUpdate(sql, id) == 1;
}
}
重建Server層
在構(gòu)建了DatabaseUtil類后曲楚,Server層的代碼如下:
/*
* 提供客戶數(shù)據(jù)服務(wù)
* */
public class CustomerService {
private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);
/*
* 獲取客戶列表
* */
public List<Customer> getCustomerList() {
String sql = "select * from customer";
List<Customer> list = DatabaseUtil.queryEntityList(Customer.class, sql, null);
return list;
}
/*
* 獲取客戶
* */
public Customer getCustomer(long id) {
String sql = "select * from customer where id = ?";
return DatabaseUtil.queryEntity(Customer.class, sql, id);
}
/*
* 創(chuàng)建客戶
* */
public boolean createCustomer(Map<String,Object> fieldMap) {
return DatabaseUtil.insertEntity(Customer.class,fieldMap);
}
/*
* 更新客戶
* */
public boolean updateCustomer(long id,Map<String,Object> fieldMap) {
//TODO
return false;
}
/*
* 刪除客戶
* */
public boolean deleteCustomer(long id) {
return DatabaseUtil.deleteEntity(Customer.class, id);
}
}
可以看到Server層的代碼非常簡潔厘唾,這樣就可以開心地寫業(yè)務(wù)邏輯代碼了。而不需要對(duì)數(shù)據(jù)庫的操作操心了龙誊。
缺陷
雖然Server層是非常的簡潔抚垃,舒服。但是相對(duì)地趟大,又創(chuàng)建了一個(gè)數(shù)據(jù)層鹤树。在這個(gè)剛建立的數(shù)據(jù)層上,顯然還是有很多不足的逊朽。
- 在getConnection()和closeConnection()上罕伯,每次調(diào)用數(shù)據(jù)庫操作,都需要重新連接數(shù)據(jù)庫和關(guān)閉數(shù)據(jù)庫叽讳,這樣的消耗很大追他。
總結(jié)
竟然我們已經(jīng)把數(shù)據(jù)庫處理這一塊跨分到一個(gè)層了坟募。那么我們就應(yīng)該對(duì)這一塊有一個(gè)更好地優(yōu)化才行。比如數(shù)據(jù)庫連接池 就是以后需要優(yōu)化的一個(gè)點(diǎn)邑狸。