日期:2014-05-17  浏览次数:20581 次

[php]标记映射和工作单元
    标记映射

        系统中可能存在两个值相同,但又不是同一个引用的对象,这样的重复对象可能是从数据库中读出来的,这样就造成了不必要的查询。

        标记映射是一个类ObjectWatcher,它负责管理进程中的领域对象,以保证进程中不出现重复对象。

        标记映射可以防止重新读取数据库查询数据,只有当ObjectWatcher类中不存在标记映射对应的对象时才去查询数据库。这样就保证了在一个进程中,一条数据只对应一个对象。

        代码很容易懂,都是一些存取数组值的操作。

        ObjectWatcher代码:

namespace demo\domain;

use \demo\domain\DomainObject;

/**
 *  标记映射
 */
class ObjectWatcher {
	private static $instance;
	// 标记映射
	private $all = array();
	
	private function __construct() {
		
	}
	
	public  static function getInstance() {
		if (!isset(self::$instance)) {
			self::$instance = new self();
		}
		
		return self::$instance;
	}
	
	/**
	 * 获得对象对应的键值
	 * @param DomainObject $obj
	 */
	public function getGobalKey(DomainObject $obj) {
		$key = get_class($obj) . '_' . $obj->getId();
		return $key;
	}
	
	/**
	 * 添加到all
	 * @param DomainObject $obj
	 */
	public static function add(DomainObject $obj) {
		$instance = self::getInstance();
		$key = $instance->getGobalKey($obj);
		$instance->all[$key] = $obj;
	}
	
	/**
	 * 从all中删除
	 * @param DomainObject $obj
	 */
	public static function delete(DomainObject $obj) {
		$instance = self::getInstance();
		$key = $instance->getGobalKey($obj);
		unset($instance->all[$key]);
	}
	
	/**
	 * 判断标记是否存在
	 * @param string $className
	 * @param int $id
	 */
	public  static function exists($className, $id) {
		$instance = self::getInstance();
		$key = "{$className}_{$id}";
		if (isset($instance->all[$key])) {
			return $instance->all[$key];
		}
		
		return null;
	}
}
        那么在哪里做标记呢?当然是生成查询对象的地方,分别有Mapper::find()、Mapper::insert()、Mapper::createObject()。 Mapper中新增加了addToMap()和getFromMap()。(其它方法没有改变,所以看以忽略吧。)

        Mapper代码:

namespace demo\mapper;

use \demo\base\AppException;
use \demo\base\ApplicationRegistry;
use \demo\domain\DomainObject;
use \demo\domain\ObjectWatcher;

/**
 * Mapper
 */
abstract  class Mapper {
	// PDO
	protected static $PDO;
	// config
	protected static  $dsn, $dbUserName, $dbPassword;
	// PDO选项
	protected static $options = array(
    	\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
    	\PDO::ATTR_ERRMODE,
    	\PDO::ERRMODE_EXCEPTION,
	); 
	
	public function __construct() {
		if (!isset(self::$PDO)) {
			// ApplicationRegistry获取数据库连接信息
			$appRegistry = ApplicationRegistry::getInstance();
			self::$dsn = $appRegistry->getDsn();
			self::$dbUserName = $appRegistry->getDbUserName();
			self::$dbPassword = $appRegistry->getDbPassword();
			
			if (!self::$dsn || !self::$dbUserName || !self::$dbPassword) {
				throw  new AppException('Mapper init failed!');
			}
			
			self::$PDO = new \PDO(self::$dsn, self::$dbUserName, self::$dbPassword, self::$options);
		}
	}
	
	/**
	 * 查找指定ID
	 * @param int $id
	 */
	public function findById($id) {
		// 从ObjectWatcher中获取
		$obj = $this->getFromMap($id);
		if (!is_null($obj)) {
			return $obj;
		}
		
		$pStmt = $this->getSelectStmt();		
		$pStmt->execute(array($id));	
		$data = $pStmt->fetch();		
		$pStmt->closeCursor();		
		if (!is_array($data) || !isset($data['id'])) {
			return $obj;
		}
		$obj = $this->createObject($data);
		
		return $obj;
	}
	
	/**
	 * 返回Collection
	 */
	public function findAll() {
		$pStmt = $this->getSelectAllStmt();
		$pStmt->execute(array());
		$raws = $pStmt->fetch