我想使用 Java 的 ORM 框架之一将域模型映射到关系数据库。不幸的是,它们似乎都没有充分支持实现多个接口(interface)的类。假设我想映射如下内容:
public interface Quotable {
}
public interface Tradable {
}
// StockIndex only implements Quotable as it cannot be trade directly
public class StockIndex implements Quotable {
}
// Stock implements both interfaces as there are market quotes and can be traded
public class Stock implements Quotable, Tradable {
}
public class Quote {
private Quotable quotable;
}
public class Trade {
private Tradable tradable;
}
所以我想要实现的是,报价可以引用任何报价表(股票、股票指数等),而交易只能引用可交易实体。我已经尝试过 OpenJPA 和(普通的)Hibernate,但没有成功,尽管后者对接口(interface)的支持看起来很有前途。
是否有任何框架可以处理我的场景?或者有什么好的理由不应该将其映射到数据库吗?如果是这样,我的模型应该如何修改?
我最初的 Hibernate 映射看起来像这样(我没有展示任何 OpenJPA 的东西,因为它不支持接口(interface)继承,或者至少我不知道如何实现):
<hibernate-mapping package="com.foo">
<class name="Quotable" table="quotable" >
<id type="java.lang.Long" column="id">
<generator class="sequence" />
</id>
<discriminator column="type" type="string" />
<subclass name="StockIndex">
<join table="stock_index" >
<key column="id"/>
<property name="name" column="name" access="field" />
</join>
</subclass>
<subclass name="Stock">
<join table="stock" >
<key column="id"/>
<property name="name" column="name" access="field" />
</join>
</subclass>
</class>
</hibernate-mapping>
这与 Hibernate documentation 中的示例几乎相同并生成一个带有 id 和字符串鉴别器列的 quotable 表,一个带有 id 和索引名称的 stock_index 表,以及一个 stock 表> 带有 ID 和股票名称。到目前为止一切顺利...
但是我应该如何处理 Tradeable 界面?我将不得不设置一个单独的层次结构并在两个层次结构中映射 Stock。我确实尝试过这个但是必须为 Stock 定义不同的实体名称(并且需要包括 this patch )但是由于外键违规这也不起作用。我尝试了其他一些不起眼的东西,但也没有用。
无论如何,两次映射 Stock 并不是一个好的解决方案,因为应用程序必须记住两次添加 Stock 实例 - 每个接口(interface)一次。我宁愿让框架自动处理这个问题。
理想情况下,Hibernate 将允许扩展多个接口(interface),例如(注意 subclass 元素上的 extends 属性):
<subclass name="Stock" extends="Quotable, Tradable" >
<join table="stock" >
<key column="id"/>
<property name="name" column="name" access="field" />
</join>
</subclass>
关于如何映射我的示例的任何其他想法?我现在了解了 <any> 看起来对我有用的元素,但我还没有理解它的所有含义。
其他框架呢?我听说 EclipseLink 也有一些接口(interface)支持,但没有很好的文档记录。
最佳答案
我认为您找不到任何能够很好地处理接口(interface)层次结构的 ORM。 所以我不会在这里谈论 ORM,但我将向您展示如何使用 Qi4j 实现您的示例。
Qi4j 是面向复合编程的实现,使用标准 Java 平台和以领域为中心的应用程序开发框架,包括从 AOP、DI 和 DDD 演变而来的概念。参见 http://qi4j.org
在 Qi4j 中,域状态是使用实体和值建模的。在以下代码示例中,我假设一切都是实体,但您的情况可能会有所不同。
由于实体仅使用接口(interface)声明,因此您的用例应该很适合。
interface Quotable { ... }
interface Tradable { ... }
interface StockIndex extends Quotable { ... }
interface Stock extends Quotable, Tradable { ... }
interface Quote {
Association<Quotable> quotable();
}
interface Trade {
Association<Tradable> tradable();
}
然后您可以将这些存储在 EntityStore 中,并使用查询 API 轻松检索它们(并以完全多态的方式)。
请注意,Qi4j EntityStores 不仅基于 SQL,还支持 NoSQL 数据库。在此处查看可用的扩展:http://qi4j.org/latest/extensions.html
如果您有更多问题,请参阅 Qi4j 文档。
关于Java ORM : Multiple (interface) inheritance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9968494/
我正在寻找一种匹配多行Parslet的方法。代码如下所示:rule(:line){(match('$').absent?>>any).repeat>>match('$')}rule(:lines){line.repeat}但是,lines将始终以无限循环结束,这是因为match('$')将无休止地重复以匹配字符串的结尾。是否可以匹配可以为空的多行?irb(main)>lines.parse($stdin.read)Thisisamultilinestring^D应该匹配成功。我错过了什么吗?我还尝试了(match('$').absent?>>any.maybe).repeat(1)>>
让多条路线去同一条路的最优雅的方式是什么ControllerAction?我有:get'dashboard',to:'dashboard#index'get'dashboard/pending',to:'dashboard#index'get'dashboard/live',to:'dashboard#index'get'dashboard/sold',to:'dashboard#index'这很丑陋。有什么“更优雅”的建议吗?一个类轮的奖励积分。 最佳答案 为什么不只有一个路由和一个Controller操作,并根据传递给它的参数来
我在使用session变量时遇到问题。我有两个名为“graduate_students_controller”和“current_students_controller”的Controller。这些Controller中的每一个都控制不同的View文件。我在这两个Controller中使用session变量来存储session信息。问题来了。假设我有两个View文件“reports/current_students_list”、“reports/graduate_students_list”,每个文件都由上述Controller单独控制。现在,如果我尝试从同一浏览器中打开这两个网页并尝
我一直在为使用acts_as_list的模型实现一些不错的交互界面,这些界面可以对我的mRails应用程序中的列表进行排序。我有一个排序函数,在每次拖放之后使用sortable_elementscript.aculo.us函数调用并设置每条记录的位置。这是在拖放完成后处理排序的Controller操作示例:defsortparams[:documents].each_with_indexdo|id,index|Document.update_all(['position=?',index+1],['id=?',id])endend现在我正在尝试对嵌套集模型(acts_as_nested
我目前一直在研究如何根据我们想要的每个条件来分离CanCan的角色。在我们的应用程序中,有很多类别(例如数学、英语、历史等),每个类别中都有很多类(class)。每个用户可以在每个类别中扮演许多不同的角色。例如,约翰可以是数学的“读者”,这意味着他可以阅读所有数学类(class)。约翰也可以是英语的“作家”,这意味着他可以阅读所有英语类(class),在类别英语中创建类(class),并仅编辑/删除他创建的英语类(class)。如果这些是John仅有的角色,他将无法在导航栏中看到类别历史记录,并且将被拒绝访问历史记录中的类(class)。这些是关系的建立方式:classUser在mod
我正在尝试在我的Rails应用程序中使用模型来从外部API检索信息。我想做的是以类似于ActiveRecord模型提供的方式(特别是关联,以及相同风格的可链接查询方法)访问我的数据模型(可能包含来自多个API调用的信息)。我最初的直觉是重新创建我想要的ActiveRecord部分并合并此API。不想“重新发明轮子”并确切地看到添加更多功能需要多少工作让我退后一步并重新评估如何处理这个问题。我找到了在没有表的情况下使用ActiveRecord的方法(请参阅:Railscast#193TablelessModel和博客文章here)并研究了ActiveRecord。因为ActiveMode
我正在尝试使用XCode和InterfaceBuilder构建一个基本的helloworld应用程序。但是,在InterfaceBuilder中,我看不到我的socket可以连接起来。我转到对象检查器Pane的连接选项卡,它显示“NewReferencingOutlet”。我想知道我的代码是否有误。在这里classHelloWorldControllerattr_accessor:hello_label,:hello_button,:hellodefawakeFromNib@hello=trueenddefchangeLabel(sender)if@hello@hello_label.
升级到rails3.2.8后出现以下错误信息NoMethodError(undefinedmethod`read_inheritable_attribute'forAdminController:Class):谁能解释一下如何解决这个错误?整个轨迹NoMethodError(undefinedmethod`read_inheritable_attribute'forAdminController:Class):vendor/plugins/ssl_requirement/lib/ssl_requirement.rb:45:in`ssl_allowed?'vendor/plugins/s
这个问题在这里已经有了答案:appendingtorakedb:seedinrailsandrunningitwithoutduplicatingdata(9个回答)关闭9年前。我想更改种子文件中的一些代码,以便在我多次运行种子命令时它不会创建重复记录。有什么方法可以从我的种子文件中修改下面的代码,这样就可以了吗?除非我弄错了,否则find_or_create_by方法在这里似乎不起作用。data_file=Rails.root.join('db/data/data.csv')CSV.foreach(data_file)do|row|TownHealthRecord.create(ci
ActiveAdmin似乎还不支持多列排序(即将多个值传递给config.sortable选项)。我看到一个老猴子补丁here但它似乎不适用于我的版本(来自Github的1.0.0.pre)。有没有办法在最新的ActiveAdmin版本上获得多个可排序的列? 最佳答案 这也是一个猴子补丁:在config/initializers或lib文件夹中创建一个新文件:multiple_columns_sorting.rbmoduleActiveAdminclassResourceController重启服务器。现在您可以使用由"_and_"