君子博学而日参省乎己 则知明而行无过矣

博客园 首页 新随笔 联系 订阅 管理

这篇内容的主要思想来自JackRabbit的WIKI,http://wiki.apache.org/jackrabbit/DavidsModel,作者在这篇文章中阐述了其JCR内容建模的观点。

软件行业对关系型数据的建模已经拥有许多经验,但是在内容仓库方面,我们还停留在早期阶段。

 

规则一:数据第一,结构其次。

我建议在软件开发的早期阶段不去理会数据类型。

尝试在开发阶段使用nt:unstructured。

设计数据结构代价高昂,而且在许多情况下,对于底层存储来说,精确描述数据结构是完全没有必要的。

应用程序中使用的数据结构自有其规律。比方说我将BLOG的修改日期保存在“lastModified”属性中,我的应用程序会自动知道从同一属性中读回修改日期,没必要进行精确描述。

更多的数据约束(如数据类型)仅在数据集成时需要。

例子:

前 面的例子中“lastModified”这个日期属性,没必要为其指定节点类型。我一定会在一开始使用“nt:unstructured”。因为我的 BLOG应用程序只是想显示最后一次修改的日期(或许还要排序),我几乎不关心它是不是一个日期。我完全相信我的程序会写入一个“日期”,也就没有必要声 明“lastModified”的节点类型。

 

规则二:控制数据层次,不要随意处之

内容的层次是一个非常有价值的资产,不要随意处之,要设计。如果你没有“好的”,可读的节点名称,可能你必须重新考虑,随意的数字比不上好名称。

将关系型数据模型转入层次型模型时,应对其过程进行斟酌。

按我的经验,内容层次要考虑访问控制,就像你的文件系统。

我更喜欢在初期讨论内容层次,在后面的阶段谈论数据类型。

例子:

我会按下面的说明为一个简单的BLOG系统建模,请注意我并未考虑节点类型。
/content/myblog
/content/myblog/posts
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping

/content/myblog/comments/iphone_shipping/i_like_it_too
/content/myblog/comments/iphone_shipping/i_like_it_too/i_hate_it

即使不进行说明,我们所有人也都理解这个例子的内容结构。

会有一点意外,为什么我没有将“comments”与“posts”保存到一起?是因为需要施加一个合理的分级访问控制。

使用上述模型,我可以轻易地允许“anonymous”用户编辑评论,而对工作区中的其它内容仅保持只读权限。

 

规则三:工作区(workspace)是用来克隆、合并和修改的

如果你的应用程序不使用clone(),merge()或update()方法,就使用单一工作区。

"Corresponding nodes"是JCR规范中的一个概念,本质上,它可以归结为不同workspace中拥有相同内容的节点。

JCR中workspace的概念非常抽象,很多开发者不理解如何运用。我建议按照下面的说明来使用它。

如果你要考虑多workspace中"Corresponding nodes"(典型的情况是拥有相同的UUID)的异同,使用多workspace是正确的。换言之,如果不同workspace中相同UUID节点的内容完全不同,那就是错误的用法。

workspace不应用来进行访问控制。不应为了区分哪些用户该看到哪些内容,而把内容划分到不同的workspace中去,JCR中的“Access Control”章节说明了正确的做法。

例子:

这样使用workspace:

  • 为项目区分1.2和1.3版本。
  • 内容的“development”、“qa”和“已发布”状态。

不要这样使用workspace:

  • 用户的home目录。
  • 区分“public”、“private”、“local”内容。
  • 不同用户的收件箱。

 

规则四:小心同名的兄弟节点

JCR中的同名兄弟节点(SNS),是为了兼容XML,SNS会引发很大的麻烦。

如果库中包含SNS,任何路径都会变得不安全,如果删除或记录SNS,它会影响该路径下的其它SNS及其子节点。

为了导入XML,或与现存的XML兼容,SNS可能是必要的,但是我绝不会使用SNS。

例子

使用

/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping

而不是

/content/blog[1]/post[1]
/content/blog[1]/post[2]
 

规则五:引用的害处

引用实现涉及完整性。引用不但增加了库管理难度,也给内容的扩展性带来了难度。

我使用路径、名称和UUID来指向其它节点,只在万不得已的时候使用引用。

 

规则六:文件就是文件

如果一个内容模型类似文件或文件夹,我会用(或扩展)nt:file,nt:folder和nt:resource。

以我的经验,许多程序天生能够集成“nt:file”,“nt:folder”,即使它们包含附加元信息,也知道如何让处理和显示它们。例如,基于JCR的Webdav或CIFS应用能够直接使用这些内容。

如果你需要存储文件名和MIME类型,那么nt:file/nt:resource恰好满足要求,如果有多个文件,在nt:folder节点会是一个好地方。

例子:

设想上传图片到BLOG条目

/content/myblog/posts/iphone_shipping
文件名和MIME类型都没什么用,考虑为其添加一个包含图片的二进制属性,也没有问题。
我建议按照下面的结构存储内容
/content/myblog/posts/iphone_shipping/attachments [nt:folder]
/content/myblog/posts/iphone_shipping/attachments/front.jpg [nt:file]
/content/myblog/posts/iphone_shipping/attachments/front.jpg/jcr:content [nt:resource]
 

规则七:ID有害

在关系型数据库中,必要的ID用来表达关系,人们在内容模型中也倾向于使用ID。

如果你的内容模型中满是以"id”结尾的属性,你恐怕没有将内容层次设计好。

的确,一些节点在其生命周期中需要安全的标识。你可能没有想到,库内建了mix:referenceable机制,实在没有必要再添加标识节点的方法。

还要记住,路径可以标识节点。

更重要的是,**mix**:referenceable意思是在你实际需要引用一个节点的时候,可以被运用到该节点上。

例子:

使用

/content/myblog/posts/iphone_shipping/attachments/front.jpg

而不是

[Blog]
- blogId
- author

[Post]
- postId
- blogId
- title
- text
- date

[Attachment]
- attachmentId
- postId
- filename
+ resource (nt:resource)
posted on 2013-07-18 04:45  刺猬的温驯  阅读(855)  评论(0)    收藏  举报