一、概念

活动记录(Active Record):一个对象,它包装数据库表或视图中某一行,封装数据库訪问。并在这些数据上添加了领域逻辑。

对象既有数据又有行为。

活动记录使用直截了当的方法。把数据訪问逻辑置于领域对象中。

 

二、实现简单活动记录

活动记录在php很多框架中都有应用。如cakephp。




Php代码  数据源架构模式之活动记录_数据


  1. <?php  
  2. /** 
  3.  * 行数据入口类 
  4.  */  
  5. class OrderGateway {  
  6.     /*定义元数据映射*/  
  7.     private $_name;  
  8.     private $_id;  
  9.    
  10.     public function __construct($id, $name) {  
  11.         $this->setId($id);  
  12.         $this->setName($name);  
  13.     }  
  14.    
  15.     public function getName() {  
  16.         return $this->_name;  
  17.     }  
  18.    
  19.     public function setName($name) {  
  20.         $this->_name = $name;  
  21.     }  
  22.    
  23.     public function getId() {  
  24.         return $this->_id;  
  25.     }  
  26.    
  27.     public function setId($id) {  
  28.         $this->_id = $id;  
  29.     }  
  30.    
  31.     /** 
  32.      * 入口类自身拥有更新操作 
  33.      */  
  34.     public function update() {  
  35.         $data = array('id' => $this->_id, 'name' => $this->_name);  
  36.    
  37.         $sql = "UPDATE order SET ";  
  38.         foreach ($data as $field => $value) {  
  39.             $sql .= "`" . $field . "` = '" . $value . "',";  
  40.         }  
  41.         $sql = substr($sql, 0, -1);  
  42.         $sql .= " WHERE id = " . $this->_id;  
  43.         return DB::query($sql);  
  44.     }  
  45.    
  46.     /** 
  47.      * 入口类自身拥有插入操作 
  48.      */  
  49.     public function insert() {  
  50.         $data = array('name' => $this->_name);  
  51.    
  52.         $sql = "INSERT INTO order ";  
  53.         $sql .= "(`" . implode("`,`", array_keys($data)) . "`)";  
  54.         $sql .= " VALUES('" . implode("','", array_values($data)) . "')";  
  55.    
  56.         return DB::query($sql);  
  57.     }  
  58.    
  59.     public static function load($rs) {  
  60.         /* 此处可加上缓存 */  
  61.         return new OrderGateway($rs['id'] ? $rs['id'] : NULL, $rs['name']);  
  62.     }  
  63.    
  64. }  
  65.   
  66. /** 
  67.  * 上面内容与行数据入口一样 
  68.  * 此类为领域逻辑,这里新建个类,不採用static 
  69.  */  
  70. class OrderAccess {  
  71.     public function find($id) {  
  72.         $sql = "SELECT * FROM order WHERE id = " . $id;  
  73.         $rs = DB::query($sql);  
  74.    
  75.         return OrderGateway::load($rs);//这里返回的行对象  
  76.     }  
  77.   
  78.     public function insert($data){  
  79.         OrderGateway::load($data)->insert();  
  80.     }  
  81.   
  82.     public function updateName($id,$name){  
  83.         $rs = array('id' => $id,'name' => $name);  
  84.         OrderGateway::load($rs)->update();  
  85.     }   
  86.   
  87.     public function findAll() {  
  88.         $sql = "SELECT * FROM order";  
  89.         $rs = DB::query($sql);  
  90.    
  91.         $result = array();  
  92.         if (is_array($rs)) {  
  93.             foreach ($rs as $row) {  
  94.                 $result[] = OrderGateway::load($row);  
  95.             }  
  96.         }  
  97.    
  98.         return $result;  
  99.     }  
  100.    
  101. }  
  102.    
  103. class DB {  
  104.    
  105.     /** 
  106.      * 这仅仅是一个运行SQL的演示方法 
  107.      * @param string $sql   须要运行的SQL 
  108.      */  
  109.     public static function query($sql) {  
  110.         echo "运行SQL: ", $sql, " <br />";  
  111.     }  
  112. }  
  113.    
  114. /** 
  115.  * client调用 
  116.  */  
  117. class Client {  
  118.     public static function main() {  
  119.         header("Content-type:text/html; charset=utf-8");  
  120.    
  121.         $access = new OrderAccess();  
  122.         $order = $access->find(1);  
  123.         echo $order->getName();  
  124.   
  125.         $access->insert(array('name' => 'xxxxx'));  
  126.         $access->update(1,'xxxxx');  
  127.     }  
  128. }  
  129.    
  130. Client::main();  
  131. ?>  


 

三、执行机制

●活动记录的本质是一个领域模型,每条活动记录负责向数据库保存数据。从数据库载入数据以及处理作用于数据之上的领域逻辑。

 

●此模式没有隐藏关系数据库的存在这个事实,因此通常使用此模式的同一时候差点儿不用其它对象关系映射模式。

 

●活动记录和行数据入口十分相似,之前也多次提及。行数据入口仅有数据库訪问而活动记录既有数据源逻辑又有领域逻辑。

 

●因为活动记录和数据库间的紧耦合,在这个模式中经常使用静态查找方法(样例採用的是新建类。这样更便于測试)。

 

●活动记录通常具有例如以下方法:

1、由SQL结果集中的一行构造一个活动记录实例(例中的OrderAccess->find方法

2、为将来对表的插入构造一个新的实例

3、用静态查找方法来包装经常使用的SQL查询和返回活动记录(样例採用新建类)

4、更新数据库并将活动记录中的数据插入数据库(例中的OrderAccess->update方法)

5、获取和设置域(例中的OrderGateway getName setName方法)

6、实现部分业务逻辑

 

四、使用场景 

1、领域模型

活动记录适用于不太复杂的领域逻辑,如CRRD等。

仅当活动记录对象和数据库中表直接相应,才比較有效。假设业务逻辑复杂,就会想到使用对象的直接关系、集合和继承等。

它们都难以映射到活动记录。

 

2、事务脚本

活动记录能够降低事务脚本代码反复的痛苦。

 

3、表模块(不考虑)