繁体   English   中英

如何为具有可扩展属性的资源编写DAO?

[英]How can I write DAOs for resources with extensible properties?

我正在尝试用Java编写嵌入式( 不是Web,不是企业 )内容管理系统,重点是组织和易用性以及可扩展到100,000个左右的项目。 用户和系统应该能够创建和定义可以与唯一资源相关联的元数据项,以便进行搜索。

例如,他们可以创建一个带有字符串值的标签“ ProjectName”。 然后,他们可以将一堆资源标记为属于“ Take Over the World”或“ Fix My Car”项目。 标签是强类型的,因此标签可以存储单个或多个字符串,整数,双精度等。每种标签类型都应具有格式化程序和输入验证器以允许编辑。

我已经决定从GUI中抽象存储模型以实现可伸缩性非常重要。 这样做的明显方法是为每个资源使用数据访问对象(DAO)。 但是,我不知道如何编写支持可变数量的标签并且可以正确缩放的DAO。

问题在于资源需要既表现为元组(用于表格查看/排序/过滤)又表现为(TagName,TagValue)映射。 对于每个GUI更新,GUI模型可能会调用这些方法数千次,因此某种索引概念会使它们都更好地工作。 不幸的是,多个标记类型意味着除非我将所有内容都作为通用对象返回并完全破坏“ TagValue instanceof Type”条件,否则它将很尴尬。

我已经研究过使用反射和Apache的DynaBeans,但是对其进行编码以与GUI模型一起使用看起来很痛苦且笨拙。 有一个更好的方法吗??? 一些库或设计模式?

所以,我的问题是,有没有更好的方法? 一些库或设计模式可以简单地完成整个工作吗?

根据您的问题,我认为“资源”是系统中的一个实体,具有与之关联的一些“标记”实体。 如果我的假设是正确的,那么这里是一个普通的DAO接口,请让我知道这是否是您的想法:

public interface ResourceDAO {
    void store(Resource resource);
    void remove(Resource resource);
    List<Resource> findResources(QueryCriteria criteria);
    void addTagsToResource(Resource resource, Set<Tag> tags);
}

这里的想法是,您将为可用的任何数据存储机制实现此接口,并且应用程序将通过此接口访问它。 实现类的实例将从工厂获得。

这符合您的想法吗?

您提到的问题的另一方面是必须应对多个不同的TagType,这些TagType根据类型需要不同的行为(需要“ TagValue instanceof Type”条件)。 访客模式可以为您提供优雅的处理方式。

我认为您不应该将这些属性中的任何一个视为实际的成员变量。 您应该有一个“属性”对象,它包含一个属性(类似于成员变量),还有一个“集合”对象,它具有多个属性集合(就像一个类)。

由于这些属性和集合实际上没有与之关联的代码,因此将它们实现为对象没有任何意义(这确实是一个麻烦)

您的属性和集合需要保存所有特定于它们的数据。 例如,如果一个字段最终被写入数据库,则需要将其表名存储在某个地方。 如果需要将其写入屏幕,则还需要将其存储在某个位置。

可以将范围/值检查“添加”到属性,因此,当定义属性是什么类型的数据时,可能会有一些文字“ MaxLength(12)”,它将实例化名为MaxLength的值12的类。并将该类存储到属性中。 每当属性的值更改时,新值就会传递到已应用于此类的每个范围检查器。 与该类关联的动作可以有很多类型。

这只是基础。 我已经设计出了类似的东西,虽然需要很多工作,但是比尝试使用简单的语言要简单得多。

我知道现在这似乎做起来太多了(如果您确实得到了我的建议,应该这样做),但是请记住这一点,最终您可能会选择“ Hmph,也许这值得一试” 。

编辑(回复评论):

我考虑过尝试使用注册表/关键内容(我们仍在讨论属性值对),但这并不完全适合。

您正在尝试将DAO装入Java对象。 这确实很自然,但是我已经将其视为解决DAO / DTO问题的一种不好的方法。 Java对象具有属性和对这些属性起作用的行为。 对于您正在做的事情,没有任何行为(例如,如果用户创建了“生日”字段,则您将不会使用对象代码来计算其年龄,因为您实际上并不知道生日是什么)。

因此,如果不使用对象和属性,该如何存储这些数据?

让我开始一个非常简单的第一步(非常接近您提到的注册表/标签系统):在要使用对象的地方,请使用哈希表。 对于属性名称,请使用键,对于属性值,请使用哈希表中的值。

现在,我将介绍为增强此简单模型而遇到的问题和解决方案。

问题:您丢失了“强类型”,并且您的数据是非常自由的格式(可能是不好的)

解决方案:为“属性”创建基类,以在哈希表中的值处使用该属性。 为IntegerAttribute,StringAttribute,DateAttribute扩展该基类。...不允许使用不适合该类型的值。 现在您可以进行强类型化,但是它是运行时而不是编译时-可能还可以,因为您的数据实际上还是在运行时定义的。

问题:格式化程序和验证程序

解决方案:能够为您的属性基类创建插件。 您应该可以为任何属性使用“ setValidator”或“ setFormatter”。 验证器/格式化程序应与属性一起使用-因此在保存属性时,您可能必须能够将它们序列化到DB。

这里的好处是,当您对属性执行“ attribute.getFormattedValue()”时,该属性已预先格式化以供显示。 如果任何验证失败,attribute.setValue()将自动调用验证器并抛出异常或返回错误代码。

问题:如何在屏幕上显示这些内容? 我们已经有getFormatted(),但是它在屏幕上显示在哪里? 我们如何使用标签? 什么样的控件应该编辑此字段?

解决方案:我将所有这些内容存储在EACH属性中。 (顺序应该存储在Class中,但是由于这是一个哈希表,因此它将无法正常工作-好吧,我们接下来将继续讨论该顺序)。 如果存储显示名称,用于呈现此显示的控件类型(文本字段,表格,日期等)和数据库字段名称,则此属性应具有与显示和数据库I /交互所需的所有信息。编写用于处理属性的O例程。

问题:Hashtable对于DAO而言是一个不良的接口。

解决方案:这是绝对正确的。 您的哈希表应该包装在一个类中,该类知道它所保存的属性的集合。 它应该能够将自身(包括其所有属性)存储到数据库中-可能借助于辅助类。 它可能应该能够通过一个方法调用来验证所有属性。

问题:如何实际使用这些东西?

解决方案:由于它们包含自己的数据,因此在系统中它们进行交互的任何位置(例如与屏幕或与DB交互),都需要一个“适配器”。

假设您要显示一个屏幕来编辑数据。 您的适配器将被传递一个框架和一个基于哈希表的DTO。

首先,它将按顺序遍历属性列表。 它会询问第一个属性(例如一个字符串),它想使用哪种控件进行编辑(比如说一个文本字段)。

它将创建一个文本字段,然后在该文本字段中添加一个侦听器以更新数据,这会将您的数据绑定到屏幕上的控件。

现在,无论何时用户更新控件,更新都将发送到属性。 该属性存储新值,完成。

(这将由于“确定”按钮的概念而变得复杂,该按钮可一次传输所有值,但是我仍然会事先设置每个绑定并将“确定”用作触发器。)

这种绑定可能很困难。 一旦使用了内置了某些绑定功能的名为“ JGoodies”的工具包,我就手动完成了这一工作,因此我不必自己编写每种可能的绑定组合,但是从长远来看,我不确定它节省了很多时间。

这太长了。 我应该有朝一日创建一个DAO / DTO工具包-我认为Java对象根本不适合DAO / DTO对象。

如果您仍然感到困惑,请随时给我发送电子邮件/即时通讯-gmail.bill.kress。

您是否要使用关系数据库? 研究面向文档的数据库(例如,couchDB)可能是值得的。 它将为您提供存储所需的任何任意强类型对象所需的灵活性,并且还使您能够查询这些对象。 我相信也有一些Java库可用于访问ouchDB。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM