具有OID的值对象

时间:2008-12-31 17:27:52

标签: java pojo oid

您能否描述在代表模型中某个实体的OID中包含POJO(通常是数据库行标识符)的优缺点?

实际上我不是在谈论与equals / hashcode等相关的问题,我应该更好地描述我的问题(我的错:))...

我们有一些代表业务对象的实体类(如产品,目录等......)。有时他们有'业务ID',例如Product可以通过其独特的ProductId找到(它有3个字段:id,type,repository)。

在我们的数据库中,除了3个业务列(id,type,repository)之外,Product表还有一个代理主键列(OID),以便于外键引用和更少的连接子句。

Product / ProductId类是我们向其他应用程序公开的API的一部分。例如,他们可以致电:

productManager.findProductById(ProductId productId);

问题是,应该或不应该将OID包含在产品或ProductId类中,因为我们知道我们的客户应该使用ProductId标识符。

优点:

  • 我可以使用OID进行另一次查找,例如

    Product p = productManager.findProductById(ProductId productId);
    Catalog c = productManager.findAllCatalogsContainingProduct(p.getOid());
    

我们习惯于通过ProductId在应用程序中进行大量查找,这样每次往返数据库时都会保存,以避免找到与ProductId匹配的OID。

缺点:

  • 我刚刚将OID暴露给客户端(让我们希望他不使用它而不是商业密钥!!)

你能列出其他优点和缺点吗?

2 个答案:

答案 0 :(得分:1)

数据库行标识符=主键?如果是这样,没有pro或con,你必须拥有它,否则你不能将POJO与其相应的数据库行相关联。

要检索产品和目录,标准的SQL方法是进行加入。例如,使用我的DAL,我可以这样做:

SearchCriteria sc = new SearchCriteria();
sc.AddBinding("ProductId", productId);
List<Entity> Products = SQL.Read(sc, new Product(new Catalog());

List<Entity> Products = SQL.Read(sc, new Catalog(new Product());

这样就不需要向呼叫者透露任何内容,也不需要往返。

答案 1 :(得分:0)

如果equals()或hashCode()的实现基于标识符,则可能会遇到问题,因为它最初可能为null,然后在对象持久化后更改。见下文:

http://java.sun.com/javase/6/docs/api/java/util/Set.html

注意:如果将可变对象用作set元素,则必须非常小心。如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的​​行为。这种禁止的一个特例是,不允许集合将自己作为一个元素包含在内。

假设您的hashCode()实现基于标识符,equals()在其比较中使用hashCode()。如果将对象添加到Set并且其标识符为null,则equals比较将执行一种方式。如果然后将对象保留在集合中,则其标识符值可能会更改,从而更改equals()和hashCode()的行为。这破坏了Set的“契约”,如上所述。

这是一个边缘案例,但值得注意的是。