我是第一次使用Doctrine2,但我认为这个问题非常通用,不依赖于特定的ORM.
Data Mapper模式中的实体是否应该知道并使用 Mapper?
我有几个具体的例子,但它们似乎都归结为同样的一般性问题.
如果我正在处理来自外部源的数据 - 例如a User有很多Messages- 并且外部源只提供最新的几个实体(如RSS提要),$user->addMessage($message)除非它知道Mapper,否则如何检查重复项,或者它通过集合"搜索"(似乎是一件低效的事情).
当然,控制器或事务脚本可以在将消息添加到用户之前检查重复项 - 但这似乎不太正确,并且会导致代码重复.
如果我有一个大型集合 - 再次User有很多Messages- User实体如何为集合提供限制和分页而不实际代理Mapper调用?
同样,控制器或交易脚本或任何使用实体可以直接使用映射来检索集合User的Messages通过次数,日期范围或其他因素的限制-而这也将导致代码重复.
答案是使用存储库并让实体知道它们吗?(至少对于Doctrine2,以及其他ORM使用的类似概念.)此时,实体仍然与Mapper相对分离.
我正在使用Data Mapper模式,我想知道处理与该模式的关系的最佳方法是什么.我花了很多时间在谷歌搜索解决方案和堆栈溢出,我发现了一些,但我仍然不是很满意他们,特别是在我将尝试解释的一个特殊情况.
我正在使用PHP,所以我将放在PHP中的代码示例.
假设我有一个表"团队"(id,name)和一个表"player"(id,name,team_id).这是一个1-N的关系.通过实现Data Mapper模式,我们将拥有以下类:Team,TeamMapper,Player和PlayerMapper.
到目前为止,一切都很简单.如果我们想要从团队中获得所有玩家怎么办?
我找到的第一个解决方案是在Team类中创建一个方法getAllPlayers(),它将使用延迟加载和代理来处理它.然后,我们可以检索这样一个团队的玩家:
$players = $team->getAllPlayers();
Run Code Online (Sandbox Code Playgroud)
我找到的第二个解决方案是直接使用PlayerMapper并将团队ID作为参数传递.就像是:
$playerMapper->findAll(array('team_id' => $team->getId()));
Run Code Online (Sandbox Code Playgroud)
但现在,让我们说我希望显示一个包含所有团队的HTML表格,以及每个团队所有玩家的"玩家"栏目.如果我们使用我描述的第一个解决方案,我们将不得不做一个SQL查询来获取团队列表和每个团队的一个查询来获取玩家,这意味着N + 1个SQL查询,其中N是团队数量.
如果我们使用我描述的第二个解决方案,我们可以先检索所有团队ID,将它们放在一个数组中,然后将其传递给播放器映射器的findAll方法,如下所示:
$playerMapper->findAll(array('team_id' => $teamIds));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们只需要运行2个查询.好多了.但我对这个解决方案仍然不满意,因为关系没有被描述到模型中,开发人员必须了解它们.
所以我的问题是:Data Mapper模式还有其他替代方案吗?通过我给出的示例,是否有一种很好的方法可以在2个查询中选择所有参与者的所有团队,并描述模型中的关系?
先感谢您!
我一直在使用ORM的活动记录和数据映射器实现,足以了解在我的大型项目中使用活动记录实现ORM的问题.现在我正在考虑将我的一个项目迁移到node.js并尝试找到我现在正在使用的类似工具.经过研究,我没有发现任何遵循数据映射器模式的node.js ORM.他们都是积极的记录.也许我错过了一些东西,你可以告诉我,对于不遵循活动记录模式的node.js,有一个很好的流行ORM吗?
我看过的图书馆:
我在看DataMapper,乍一看似乎使用了ActiveRecord ORM模式.其他人说它使用DataMapper和/或Domain Object模式.
这些模式有什么区别?
我正在开始我的第一个Sinatra应用程序,我正在尝试使用DataMapper.一切都处于早期阶段,因为我无法实际创建数据库.当我尝试访问我的页面时,我收到"LoadError:没有这样的文件加载 - dm-sqlite-adapter".
这是我的Sinatra App到目前为止的代码:
require 'rubygems'
require 'sinatra'
require 'dm-core'
require 'dm-timestamps'
# Also tried require 'datamapper' , but the same issue shows up
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/raffle.db")
class Raffle
include DataMapper::Resource
property :id, Serial
property :firstName, String
property :lastName, String
property :email, String
property :created_at, DateTime
end
# Create, upgrade, or migrate DB Tables
DataMapper.auto_upgrade!
Run Code Online (Sandbox Code Playgroud)
我安装了宝石,作为宝石列表输出:
*** LOCAL GEMS ***
activemodel (3.0.9, 3.0.3)
activerecord (3.0.9, 3.0.3)
activesupport (3.0.9, 3.0.3)
addressable (2.2.6)
arel (2.0.10, 2.0.4)
bcrypt-ruby (2.1.4)
builder (2.1.2)
bundler (1.0.15) …Run Code Online (Sandbox Code Playgroud) 我想在我现有的Sinatra应用程序中添加一个ORM.虽然我还没有尝试过ActiveRecord,但我还是通过了Datamapper,Sequel和ActiveRecord.
Datamapper似乎很容易,但我经常面临" 在一个进程中使用什么ORM多个数据库连接sinatra应用程序? "中讨论的问题,但无法理解它的解决方案和根本原因.
有没有建议选择合适的,以绩效为导向的ORM?
我有一个简单的MySQL表:
% mysql -u rampion dev -e 'describe person'
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | UNI | NULL | auto_increment |
| uid | varchar(256) | NO | PRI | NULL | |
+-------+--------------+------+-----+---------+----------------+
Run Code Online (Sandbox Code Playgroud)
我想运行一个简单的DataMapper脚本:
# temp.rb
require 'rubygems'
require 'datamapper'
DataMapper::Logger.new($stdout, :debug)
DataMapper.setup(:default, "mysql://rampion@localhost/dev")
class Person
include DataMapper::Resource
property :id, Serial
property :uid, String
end
DataMapper.finalize
p Person.first_or_create(:uid => 'Steve')
Run Code Online (Sandbox Code Playgroud)
但是当我运行它时,我得到动态链接器错误:
% ruby …Run Code Online (Sandbox Code Playgroud) 在Datamapper中,如何指定两个字段的组合必须是唯一的.例如,类别必须在域中具有唯一名称:
class Category
include DataMapper.resource
property :name, String, :index=>true #must be unique for a given domain
belongs_to :domain
end
Run Code Online (Sandbox Code Playgroud) 我们刚刚将虚拟机升级到我认为相同的ruby配置(通过RVM ...... Ruby 1.9.2,Rails 3.0.7,DataMapper 1.1.0).最大的区别是我们从MySQL 5.0到5.1.
出于某种原因,在我们的旧虚拟机上工作的完全相同的代码/ database.yml现在在我们尝试连接到数据库时的新代码上失败了.
问题是这个YAML:
mysql_defaults: &mysql_defaults
adapter: mysql
encoding: UTF-8
username: user
password: pass
host: localhost
development:
<<: *mysql_defaults
database: devdb
production:
<<: *mysql_defaults
database: productiondb
host: master.db.site.com
Run Code Online (Sandbox Code Playgroud)
只是扩展到:
"mysql_defaults" => {
"adapter"=>"mysql",
"encoding"=>"UTF-8",
"username"=>"user",
"password"=>"pass",
"host"=>"localhost"
},
"development" => {
"adapter"=>"mysql",
"encoding"=>"UTF-8",
"username"=>"user",
"password"=>"pass",
"host"=>"localhost"
},
"production" => {
"adapter"=>"mysql",
"encoding"=>"UTF-8",
"username"=>"user",
"password"=>"pass",
"host"=>"localhost"
}
Run Code Online (Sandbox Code Playgroud)
代替:
"mysql_defaults" => {
"adapter"=>"mysql",
"encoding"=>"UTF-8",
"username"=>"user",
"password"=>"pass",
"host"=>"localhost"
},
"development" => {
"adapter"=>"mysql",
"encoding"=>"UTF-8",
"username"=>"user",
"password"=>"pass",
"host"=>"localhost", …Run Code Online (Sandbox Code Playgroud) 我正在用PHP编写一个系统,它必须写入三个持久层:
原因是遗留系统无法更改.
我想使用DataMapper模式,我正在尝试建立实现我想要的最佳方式.我有一个如下界面:
<?php
$service = $factory->getService()->create($entity);
?>
Run Code Online (Sandbox Code Playgroud)
为简洁起见,下面是一些人为的和减少的代码:
<?php
class Post extends AbstractService
{
protected $_mapper;
public function create(Entity $post)
{
return $this->_mapper->create($post);
}
}
class AbstractMapper
{
protected $_persistence;
public function create(Entity $entity)
{
$data = $this->_prepareForPersistence($entity);
return $this->_persistence->create($data);
}
}
?>
Run Code Online (Sandbox Code Playgroud)
我的问题是因为有三个持久层,因此每个都可能需要三个映射器.我想要一个干净的设计模式灵感的界面,使这项工作.
我认为它有三个选项:
这些解决方案中的每个解决方案都让我觉得错误,并且会感谢任何可能适合这种情况的反馈/认可的设计模式.
datamapper ×10
ruby ×5
orm ×4
php ×3
oop ×2
sinatra ×2
activerecord ×1
architecture ×1
indexing ×1
javascript ×1
mysql ×1
node.js ×1
sqlite ×1
typeorm ×1
yaml ×1