CouchDB中的子对象与Java

时间:2013-05-06 14:40:56

标签: json serialization nosql couchdb abstract-class

更新:感谢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.customerCustomer的实例,实例化一个实例,并且从JSON数据设置其字段。

但是,使用items记录会变得更加棘手,因为我不知道Product的哪个子类要为列表中的每个元素实例化(我无法初始化一个实例抽象类或接口)。

我试图通过存储带有数据的完整类名来解决这个问题(例如,每个Product记录将包含一个额外的@class字段,以指示序列化的对象类型,等等在反序列化时应该初始化什么类型)但这意味着我为自己创建了一个问题,例如,我将该类移动到另一个包(因为存储的@class值将无效)。虽然可以通过迁移脚本(或其他方法)来缓解这种情况,但感觉好像我错过了一个基本点,并且正在围攻它。

有人可以告诉我,我做错了什么吗?有没有更优雅的方法,这将使我不必使用序列化代码,因为我的理解是NoSQL数据库应该减少开发人员花在编写持久性代码上的时间?

为了它的价值,我尝试过使用Ektorp和LightCouch,并且两者都有类似的问题。

1 个答案:

答案 0 :(得分:2)

这是对象关系映射的典型问题。这不仅限于文档数据库。

您可以选择三种方法:

  1. 维护数据库中从class-id到实际类的映射
  2. 在应用程序中维护此映射
  3. 不要映射。但在移动类时更新数据库中的文档。
  4. 根据我的经验,大多数人选择备选方案2,因为他们希望保持数据库独立于应用程序详细信息(类/包)。

    在一个较早的应用程序中,我遇到了同样的问题,我只是为那些已移动的类维护了一个映射表。容易做到。

    如果您不想使用序列化代码,那么您可以使用MongoDB可用的任何对象持久性框架。