更新:感谢funql / Kim。我理解你的观点 - 所以如果你允许我提出一个后续问题,那么实际上有一种方法可以使用Couch来做对象持久性(就像Funql for Mongo所建议的那样)吗?据我在开始这个项目之前的理解,这是NoSQL DB的一个好处 - 你不需要担心DAO层,你几乎可以将一个对象转储到一个Document中并根据需要将其拉出来,没有麻烦,让你的类定义完全暗示模式定义,我看不出它在MongoDB中工作的根本原因,而不是CouchDB?
我在企业应用程序中第一次使用CouchDB,感觉我错过了一些关于NoSQL思维方式的基本知识。
假设您有以下Java类:
public class Customer { ... }
public abstract class Product { ... } // could just as well be an interface
public class ProductA extends Product { ... };
public class ProductB extends Product { ... };
public class Sale {
private String transactionId;
private Customer customer;
private List<Product> items;
// ...
}
当将Sale存储到Couch数据库(或其他文档存储数据库)时,我最终会得到一个包含整个Sale的单个文档,这就是我想要的。但是,当我开始尝试存储/检索实现接口的抽象类或类时,我遇到了问题。我的销售记录通常看起来像这样(简化):
{
"transactionId": "12345",
"customer": { "name": "Joe Soap" },
"items": [
{
"name": "Coke",
"price": 12.99,
"qty": 1
},
{
"name": "Minced meat",
"weight": 1.23,
"price": 49.99
}
]
}
现在检索该数据对于客户来说很简单 - 我可以使用自定义序列化器/反序列化器并使用反射来告诉Sale.customer
是Customer
的实例,实例化一个实例,并且从JSON数据设置其字段。
但是,使用items
记录会变得更加棘手,因为我不知道Product
的哪个子类要为列表中的每个元素实例化(我无法初始化一个实例抽象类或接口)。
我试图通过存储带有数据的完整类名来解决这个问题(例如,每个Product
记录将包含一个额外的@class
字段,以指示序列化的对象类型,等等在反序列化时应该初始化什么类型)但这意味着我为自己创建了一个问题,例如,我将该类移动到另一个包(因为存储的@class
值将无效)。虽然可以通过迁移脚本(或其他方法)来缓解这种情况,但感觉好像我错过了一个基本点,并且正在围攻它。
有人可以告诉我,我做错了什么吗?有没有更优雅的方法,这将使我不必使用序列化代码,因为我的理解是NoSQL数据库应该减少开发人员花在编写持久性代码上的时间?
为了它的价值,我尝试过使用Ektorp和LightCouch,并且两者都有类似的问题。
答案 0 :(得分:2)
这是对象关系映射的典型问题。这不仅限于文档数据库。
您可以选择三种方法:
根据我的经验,大多数人选择备选方案2,因为他们希望保持数据库独立于应用程序详细信息(类/包)。
在一个较早的应用程序中,我遇到了同样的问题,我只是为那些已移动的类维护了一个映射表。容易做到。
如果您不想使用序列化代码,那么您可以使用MongoDB可用的任何对象持久性框架。