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());
}
一个简单的例子,让我们了解到了数据持久层的概念和重要性,同时也体会到了一些重要的思想和技术方法的应用--分层设计,解耦合,开闭原则,设计模式。