简体   繁体   English

Data Mapper通常是什么样的?

[英]What does a Data Mapper typically look like?

I have a table called Cat , and an PHP class called Cat . 我有一个名为Cat的表,还有一个名为Cat的PHP类。 Now I want to make a CatDataMapper class, so that Cat extends CatDataMapper . 现在我想创建一个CatDataMapper类,以便Cat extends CatDataMapper

I want that Data Mapper class to provide basic functionality for doing ORM, and for creating, editing and deleting Cat. 我希望Data Mapper类提供执行ORM以及创建,编辑和删除Cat的基本功能。

For that purpose, maybe someone who knows this pattern very well could give me some helpful advice? 为此目的,也许能够很好地了解这种模式的人可以给我一些有用的建议吗? I feel it would be a little bit too simple to just provide some functions like update(), delete(), save(). 我觉得提供一些函数如update(),delete(),save()会有点太简单了。

I realize a Data Mapper has this problem: First you create the instance of Cat, then initialize all the variables like name, furColor, eyeColor, purrSound, meowSound, attendants, etc.. and after everything is set up, you call the save() function which is inherited from CatDataMapper. 我意识到数据映射器有这个问题:首先你创建了Cat的实例,然后初始化所有变量,如name,furColor,eyeColor,purrSound,meowSound,atte者等等。在设置好所有内容之后,你调用save( )函数,它继承自CatDataMapper。 This was simple ;) But now, the real problem: You query the database for cats and get back a plain boring result set with lots of cats data. 这很简单;)但现在,真正的问题是:你在数据库中查询猫并获得一个包含大量猫数据的无聊结果集。

PDO features some ORM capability to create Cat instances. PDO具有一些ORM功能来创建Cat实例。 Lets say I use that, or lets even say I have a mapDataset() function that takes an associative array. 让我说我使用它,或者甚至说我有一个带有关联数组的mapDataset()函数。 However, as soon as I got my Cat object from a data set, I have redundant data. 但是,只要我从数据集中获取Cat对象,就会有冗余数据。 At the same time, twenty users could pick up the same cat data from the database and edit the cat object, ie rename the cat, and save() it, while another user still things about setting another furColor. 同时,20个用户可以从数据库中获取相同的cat数据并编辑cat对象,即重命名cat,并保存()它,而另一个用户仍然可以设置另一个furColor。 When all of them save their edits, everything is messed up. 当所有人都保存他们的编辑时,一切都搞砸了。

Err... ok, to keep this question really short: What's good practice here? 呃...好吧,保持这个问题非常简短:这里有什么好的做法?

From DataMapper in PoEA 来自PoEA中的DataMapper

The Data Mapper is a layer of software that separates the in-memory objects from the database. Data Mapper是一个软件层,用于将内存中对象与数据库分开。 Its responsibility is to transfer data between the two and also to isolate them from each other. 它的职责是在两者之间传输数据,并将它们彼此隔离。 With Data Mapper the in-memory objects needn't know even that there's a database present; 使用Data Mapper,即使存在数据库,内存中的对象也不需要知道; they need no SQL interface code, and certainly no knowledge of the database schema. 他们不需要SQL接口代码,当然也不了解数据库模式。 (The database schema is always ignorant of the objects that use it.) Since it's a form of Mapper (473), Data Mapper itself is even unknown to the domain layer. (数据库模式总是不知道使用它的对象。)由于它是Mapper(473)的一种形式,因此数据映射器本身甚至不为域层所知。

Thus, a Cat should not extend CatDataMapper because that would create an is-a relationship and tie the Cat to the Persistence layer. 因此,Cat不应该扩展CatDataMapper,因为这会创建一个is-a关系并将Cat绑定到持久层。 If you want to be able to handle persistence from your Cats in this way, look into ActiveRecord or any of the other Data Source Architectural Patterns. 如果您希望能够以这种方式处理Cats的持久性,请查看ActiveRecord或任何其他数据源架构模式。

You usually use a DataMapper when using a Domain Model. 在使用域模型时,通常使用DataMapper。 A simple DataMapper would just map a database table to an equivalent in-memory class on a field-to-field basis. 一个简单的DataMapper只是在一个字段到字段的基础上将数据库表映射到等效的内存中类。 However, when the need for a DataMapper arises, you usually won't have such simple relationships. 但是,当出现对DataMapper的需求时,通常不会有这样简单的关系。 Tables will not map 1:1 to your objects. 表格不会将1:1映射到您的对象。 Instead multiple tables could form into one Object Aggregate and viceversa. 相反,多个表可以形成一个Object Aggregate而反之亦然。 Consequently, implementing just CRUD methods, can easily become quite a challenge. 因此, 实施CRUD方法很容易成为一个挑战。

Apart from that, it is one of the more complicated patterns (covers 15 pages in PoEA), often used in combination with the Repository pattern among others. 除此之外,它是更复杂的模式之一(PoEA中包含15页),通常与Repository模式结合使用。 Look into the related questions column on the right side of this page for similar questions. 查看本页右侧的相关问题栏,了解类似问题。

As for your question about multiple users editing the same Cat, that's a common problem called Concurrency . 至于你关于多个用户编辑同一个Cat的问题,这是一个称为并发的常见问题。 One solution to that would be locking the row , while someone edits it. 一个解决方案是锁定行 ,而有人编辑它。 But like everything, this can lead to other issues . 但就像所有事情一样,这可能导致其他问题

If you rely on ORM's like Doctrine or Propel , the basic principle is to create a static class that would get the actual data from the database, (for instance Propel would create CatPeer), and the results retrieved by the Peer class would then be "hydrated" into Cat objects. 如果依靠ORM的象学说行走 ,其基本原理是创建一个静态类会从数据库中获取的实际数据,(例如行走会造成CatPeer),然后由Peer类检索的结果将是“水合“成猫对象。

The hydration process is the process of converting a "plain boring" MySQL result set into nice objects having getters and setters. 水化过程是将“无聊的”MySQL结果集转换为具有getter和setter的漂亮对象的过程。

So for a retrieve you'd use something like CatPeer::doSelect() . 因此,对于检索,您可以使用像CatPeer::doSelect()这样的东西。 Then for a new object you'd first instantiate it (or retrieve and instance from the DB): $cat = new Cat(); 然后,对于一个新对象,您首先要实例化它(或从数据库中检索和实例): $cat = new Cat();

The insertion would be as simple as doing: $cat->save(); 插入就像执行一样简单: $cat->save(); That'd be equivalent to an insert (or an update if the object already exists in the db... The ORM should know how to do the difference between new and existing objects by using, for instance, the presence ort absence of a primary key). 这相当于一个插入(或者如果对象已经存在于db中则更新...... ORM应该知道如何通过使用,例如,存在或不存在主要对象来区分新对象和现有对象键)。

Implementing a Data Mapper is very hard in PHP < 5.3, since you cannot read/write protected/private fields. 在PHP <5.3中实现数据映射器非常困难,因为您无法读取/写入受保护/私有字段。 You have a few choices when loading and saving the objects: 加载和保存对象时有几个选择:

  1. Use some kind of workaround, like serializing the object, modifying it's string representation, and bringing it back with unserialize 使用某种解决方法,例如序列化对象,修改它的字符串表示形式,并使用反序列化将其恢复
  2. Make all the fields public 公开所有字段
  3. Keep them private/protected, and write mutators/accessors for each of them 保持私密/受保护,并为每个人编写变更器/访问器

The first method has the possibility of breaking with a new release, and is very crude hack, the second one is considered a (very) bad practice. 第一种方法有可能破坏新版本,并且是非常粗糙的黑客,第二种方法被认为是(非常)不好的做法。

The third option is also considered bad practice, since you should not provide getters/setters for all of your fields, only the ones that need it. 第三种选择也被认为是不好的做法,因为您不应该为所有字段提供getter / setter,只提供需要它的字段。 Your model gets "damaged" from a pure DDD (domain driven design) perspective, since it contains methods that are only needed because of the persistence mechanism. 您的模型从纯DDD(域驱动设计)角度“受损”,因为它包含仅由于持久性机制而需要的方法。 It also means that now you have to describe another mapping for the fields -> setter methods, next to the fields -> table columns. 这也意味着现在你必须描述字段的另一个映射 - > setter方法,在字段旁边 - >表列。

PHP 5.3 introduces the ability to access/change all types of fields, by using reflection: PHP 5.3引入了使用反射访问/更改所有类型字段的功能:

http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php http://hu2.php.net/manual/en/reflectionproperty.setaccessible.php

With this, you can achieve a true data mapper, because the need to provide mutators for all of the fields has ceased. 有了这个,您就可以实现真正的数据映射器,因为为所有字段提供mutator的需求已经停止。

PDO features some ORM capability to create Cat instances. PDO具有一些ORM功能来创建Cat实例。 Lets say I use that, or lets even say I have a mapDataset() function that takes an associative array. 让我说我使用它,或者甚至说我有一个带有关联数组的mapDataset()函数。 However, as soon as I got my Cat object from a data set, I have redundant data. 但是,只要我从数据集中获取Cat对象,就会有冗余数据。 At the same time, twenty users could pick up the same cat data from the database and edit the cat object, ie rename the cat, and save() it, while another user still things about setting another furColor. 同时,20个用户可以从数据库中获取相同的cat数据并编辑cat对象,即重命名cat,并保存()它,而另一个用户仍然可以设置另一个furColor。 When all of them save their edits, everything is messed up. 当所有人都保存他们的编辑时,一切都搞砸了。

In order to keep track of the state of data typically and IdentityMap and/or a UnitOfWork would be used keep track of all teh different operations on mapped entities... and the end of the request cycle al the operations would then be performed. 为了通常跟踪数据的状态并且将使用IdentityMap和/或UnitOfWork,跟踪映射实体上的所有不同操作......以及请求周期的结束,然后将执行操作。

keep the answer short: You have an instance of Cat. 保持答案简短:你有一个Cat的实例。 (Maybe it extends CatDbMapper, or Cat3rdpartycatstoreMapper) You call: (也许它扩展了CatDbMapper,或者Cat3rdpartycatstoreMapper)你可以调用:

$cats = $cat_model->getBlueEyedCats();
//then you get an array of Cat objects, in the $cats array

Don't know what do you use, you might take a look at some php framework to the better understanding. 不知道你用了什么,你可能会看看一些php框架,以便更好地理解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM