2

更新:感谢 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;
  // ...
}

将销售存储到 Couch 数据库(或其他文档存储数据库)时,我最终得到一个包含整个销售的单个文档,这就是我想要的。但是,当我开始尝试存储/检索抽象类或实现接口的类时,我遇到了一个问题。我的销售记录通常看起来像这样(简化):

{
   "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,并且两者都有类似的问题。

4

1 回答 1

2

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

您可以选择三种方法:

  1. 在数据库中维护从类 ID 到实际类的映射
  2. 在应用程序中维护此映射
  3. 不要映射。但是在移动类时更新数据库中的文档。

根据我的经验,大多数人选择替代方案 2,因为他们希望使数据库独立于应用程序细节(类/包)。

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

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

于 2013-05-08T08:46:24.763 回答