日期:2014-05-17 浏览次数:20670 次
系统中可能存在两个值相同,但又不是同一个引用的对象,这样的重复对象可能是从数据库中读出来的,这样就造成了不必要的查询。
标记映射是一个类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