1.1
持久化:通過持久化過程,将記憶體中的資料儲存到資料庫(或)其他媒介)以備日後隻用,是為持久化。
持久層:專注于資料持久化的一個相對獨立的領域。
所謂持久層,我們不妨從回答下面幾個問題來嘗試了解:
1.如果表示層發生變化,需要從JSP遷移到Java WebStartClient,我們的資料持久層代碼是否需要重新編譯。
2.如果業務邏輯層發生變化,那麼資料化持久話代碼是否需要重新編譯。
3.如果底層資料持久化機制發生了改變,比如更換資料庫,那麼,系統的非持久化部分代碼,包括表示層,業務邏輯層是否重新編譯。
1.2
耦合:事物之間的互相關系。
解耦合:采用一些手段降低關聯的緊密程度。
解耦合設計:應用層解耦合—應用邏輯和資料邏輯分離;資源層解耦合—邏輯結構和實體結構的相分離。
解耦思想的自然演進和持久層的解耦合:以網上商店購物結算的處理過程為例。
<此處讀者以人類曆史的發展過程來整理作者的演繹過程,并對其示例代碼略作整合,并忽略了異常處理>
原始社會—原始個體獨立生産自己所需:
業務邏輯和資料通路代碼混雜,一個過程負責完成所有工作。
public BigDecimal calcAmount(String customerID, BigDecimal amount) throws Exception {
connection conn = null;
Statement statement = null;
class.forName("Oracle.jdbc.driver.OracleDriver");
conn = DriverManager.getConnection(
"JDBC:oracle:thin:@dbserver:1521:forum",
"MyUserName", "MyPasswor");
PreparedStatement stmt_customer = conn.prepareStatement("select level from customer where id = ?");
stmt_customer.setString(1, customerID);
ResultSet rset_customer = stmt_customer.executeQuery();
if(rset_customer.next())
{
int customerLevel = rset_customer.getInt(1);
PreparedStatement stmt_promotion = conn.prepareStatement(
"select ration from promotion where cust_level = ?");
stmt_promotion.setInt(1, customerLevel);
ResultSet rset_promotion = stmt_promotion.executeQuery();
Double ratio = 1;
if(rset_promotion.next())
{
ratio = rset_promotion.getDouble(1);
}
amount = amount.multi(new BigDecimal(ratio));
PreparedStatement stmt_updateCustomer = conn.prepareStatement(
"update custiomer set sum_amount = sum_amount + ? where id = ?");
stmt_updateCustomer.setDouble(1, amount.doubleValue());
stmt_updateCustomer.setString(2, customerID);
stmt_updateCustomer.executeUpdate();
stmt_updateCustomer.close();
rset_promotion.close():
stmt_promotion.close():
}
rset_customer.close();
stmt_customer.cloase();
return amount;
}
奴隸社會—個體專注自己的生産,并用産出與他人交換,簡單的獨立和合作:
将一些變化的,和影響性能的操作進行簡單的封裝,比如将使用者資訊通過配置檔案實作,用一個對象負責資料庫連接配接池的管理,以提高性能。
從配置檔案讀取資料庫連接配接的配置片段:
……
Class.forname(config.getValue(“JDBC_DRIVER”);
Conn = DriverManager.getConnection(config.getValue(“DB_URL”), config.getValue(“DB_USER”), config.getValue(“DB_PASSWORD”));
……
連接配接池管理類:
Public class DBHelper{
Public static Connection getConnection() {
//從連接配接池擷取資料庫連接配接
}
Public static releaseConnection(Connection conn) {
//将使用完的連接配接傳回到連接配接池
}
}
Public class MyDBPersistence {
……
Connection conn = null;
try {
conn = DBHelper.getConnection();
……
) finally {
DBHelper.releaseConnection(conn);
}
……
}
封建社會—專業作坊的出現使得生産力大大提高:
引入DAO(Data Access Object)模式(DAO實際上是Data Accessor模式和Active Domain Object模式的組合),實作
業務邏輯層的分離
資料通路底層實作的分離
資源管理和排程的分離(資料通路層的分離,使得資源的管理和緩存機制可以更好的得以應用,進而提高性能)
資料抽象(對底層資料封裝-對象Bean 使得業務邏輯可以通路更有意義的屬性名稱,而不是資料表的字段)。
業務邏輯層代碼:
public BigDecimal calcAmount(String customerID, BigDecimal amount) {
//根據客戶ID獲得客戶記錄
Customer customer = CustomerDAO.getCustomer(customerID);
//根據客戶等級獲得打折規則
Promotion promotion = PromotionDAO.getPromotion(customer.getLevel());
//累計客戶總消費額,并儲存結果
customer.setSumAmount(customer.getSumAmount().add(amount));
customerDAO.save(customer);
return amount.getmultiply(promotion.getRation());
}
實體對象<Active Domain Object>:
普通的實體bean(代碼省略)。
資料通路層代碼<Data Accessor>:
public class customerDAO {
public static Customer getCustomer(String ID) {
Connection conn;
ResultSet rset_customer = null;
PreparedStatement stmt_customer = null;
conn = DBHelper.getConnection();
……
……
……
Customer customer = new Customer():
Customer.setID(rset_customer.getInt(1);
……
DBHelper.releaseConnection(conn);
return customer
}
Public static void save(Customer customer) {
//同上
}
}
資本主義社會—面對複雜的環境,更加規模化和專業化:
對于一個産品而言,面臨着複雜多變的應用環境,如采用不同的資料庫,我們引進Factory模式和Proxy模式來實作對不同資料庫的通路機制,以更好的展現開閉原則—對擴充開放,對變化封裝。
public interface CustomerDAO {
public Customer getCustomer(String custID);
public void save (Customer customer);
}
public class CustomerDAOImp_MySQL implements CustomerDAO {
}
public class CustomerDAOImp_Oracle implement CustomerDAO {
}
public class DAOFactory {
private static HashMap daomap = null;
public static Object getDAO(Class daoInterface) ;
Initial();
Object dao = daoMap.get(interface);
if( null == dao)
{
//報錯
}
return dao;
}
public static synchronized void initial() {
if(null == daomap) {
daoMap = DAOConfig.load(); //根據配置檔案加載DAO實作
}
}
public BigDecimal calcAmount(String customerID, BigDecimal amount) {
CustomerDAO customerDAO = (Customer)DAOFactory.getDAO(CustomerDAO.calss);
//根據客戶ID獲得客戶記錄
Customer customer = CustomerDAO.getCustomer(customerID);
//根據客戶等級獲得打折規則
Promotion promotion = PromotionDAO.getPromotion(customer.getLevel());
//累計客戶總消費額,并儲存結果
customer.setSumAmount(customer.getSumAmount().add(amount));
customerDAO.save(customer);
return amount.getmultiply(promotion.getRation());
}
calcAmount中似乎又夾雜了一點資料庫操作的代碼,當然事情不可能十全十美,總歸是要有所取舍。不過我們繼續用proxy模式對其進行重構優化。
public class CustomerProxy {
public static Customer getCustomer(String customerID) {
CustomerDAO custDAO = (CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
return custDAO.getCustomer(customerID);
}
public static void save(Customer customer) {
……
}
}
PromotionProxy類此。
再看看我們calcAmount:
public BigDecimal calcAmount(String customerID, BigDecimal amount) {
//根據客戶ID獲得客戶記錄
Customer customer = CustomerProxy.getCustomer(customerID);
//根據客戶等級獲得打折規則
Promotion promotion = PromotionProxy.getPromotion(customer.getLevel());
//累計客戶總消費額,并儲存結果
customer.setSumAmount(customer.getSumAmount().add(amount));
customerDAO.save(customer);
return amount.getmultiply(promotion.getRation());
}
一個簡單的例子,讓我們了解到了資料持久層的概念和重要性,同時也體會到了一些重要的思想和技術方法的應用--分層設計,解耦合,開閉原則,設計模式。