在这篇文章中,JavaLobby的Daniel Spiewak,某种名为ActiveObjects的创造者,对Hibernate进行了一些批评,并将其与Ruby的ActiveRecord和ActiveObjects进行了负面比较。我总是喜欢阅读有见地的批评,但在这个案例中,Daniel似乎是将这些全新的框架与我在加入JBoss之前发布的Hibernate2进行了比较。他说
想想看,你上次尝试从头开始配置Hibernate项目是什么时候?你必须写比代码更多的XML!
呃。上次我和Hibernate3的大多数用户尝试配置Hibernate项目时,他们唯一需要写的XML是persistence.xml文件,它包含基本的数据库连接设置。如果Daniel发现了一些神奇的方法,可以自动推断用户想要连接的数据库,而无需用户输入JDBC URL,我非常愿意听到关于它的信息;:-)
Daniel继续声称
我们有一个简单的表,它与另一个表有一对多的关系。每个表都有几个值和一个主键(id)。现在在Hibernate中,我们会使用一对Java Bean和大量的映射XML来映射这个模式。
当然,Hibernate Annotations自2005年初以来就已经存在了,人们没有必要再在XML中定义映射。
因此,为了解决这个所谓的“大量XML”问题,Daniel受到了Ruby的ActiveRecord的启发。他给出的代码示例如下
class Person < ActiveRecord::Base belongs_to :company end
class Company < ActiveRecord::Base has_many :people end
在这个时候,大多数开发者都在想“嗯,好吧,那我怎么从我的代码中知道Company有哪些属性呢?我的IDE怎么自动补全它们呢?”当然,Rails的开发者对这个问题有一个快速的回答“哦,只要打开你的数据库客户端,看看数据库!”然后,假设你完美地了解ActiveRecord的自动大写和复数化规则,你将能够猜测出你自己的Company类,并手动输入它们。
不知何故,对Ruby语言的兴奋已经扭曲了他们的认知,以至于这些人竟然认为这是/好事/!
幸运的是,丹尼尔的产品并没有采用这种荒谬的方法。在ActiveObjects中,你必须/确实/列出Company的属性。Company我们的
public interface Company extends Entity { public String getName(); public void setName(String name); public String getTickerSymbol(); public void setTickerSymbol(String tickerSymbol); @OneToMany public Person[] getPeople(); }
类看起来像这样
哦,除了它根本不是类 :-/ 所以如果我有一些执行业务逻辑或验证内部约束的方法,我无处可写代码!现在,理论上,可以通过使用抽象类而不是接口,并使用CGLIB之类的字节码库来生成实现类来解决这个问题。不幸的是,丹尼尔的产品目前不支持这一点,因为他的实现使用了JDK动态代理。所以,ActiveObjects到底解决了什么问题?编写getName()和setName()
@Entity public class Company extends Entity { private String name; private String tickerSymbol; @OneToMany private Person[] people; public void getName() { return name; } public void setName(String name) { this.name = name; } public void getTickerSymbol() { return tickerSymbol; } public void setTickerSymbol(String tickerSymbol) { this.tickerSymbol = tickerSymbol; } public Person[] getPeople() { return people; } public void setPeople(Person[] people) { this.people = people; } }
/真的/降低了你的项目效率吗?拜托,我的IDE可以只用一个键盘快捷键就完成!Hibernate或其他JPA实现中的等效代码如下(其中Entity是我编写的一个定义了id
属性的类。)。
请注意,我无需编写任何XML,更不用说山脉
那么多了。我真的不认为这段代码比ActiveObjects版本复杂或难以输入(事实上,在现代IDE中,生成它可能需要的按键更少)。更好的是,我不需要使用任何奇怪的API来实例化这个类。我只需使用new
即可。CompanygetName()而且我认为这段代码比ActiveRecord版本更清晰、更明确。面向对象编程非常适用于建模像Person
这样的业务领域对象。Rails本质上将业务领域模型委托给数据库,这似乎非常奇怪。
更新
Emmanuel刚刚注意到,在这个页面上声称
AO也有潜力比Hibernate等更传统的ORM有显著更好的性能,因为它具有多级缓存系统的懒加载。