值列表处理程序提供搜索和迭代功能。要执行搜索,值列表处理程序使用数据访问对象来执行查询并从数据库中检索匹配的结果。
问题
您有一个想要遍历大型结果列表的远程客户端。
动因
解决方案
使用值列表处理程序搜索,缓存结果,并允许客户端遍历并从结果中选择项目。值列表处理程序提供搜索和迭代功能。要执行搜索,值列表处理程序使用数据访问对象来执行查询并从数据库中检索匹配结果。对于将业务对象作为实体bean实现的应用程序,这将绕过使用EJB查找器。
结构
让我们使用UML类图表示解决方案的基本结构,本节中的UML序列图介绍了解决方案的动态机制。
类图
序列图
参与者与职责
Client - 客户端是需要执行返回大量结果的查询的任何客户端。客户端可以是想要向用户显示搜索结果的表示层组件。客户端也可以是封装ValueListHandler的会话bean 。
ValueListIterator - ValueListIterator提供了一种迭代机制,使用以下方法迭代ValueList的内容。
ValueListHandler - ValueListHandler执行搜索并获取查询结果,它在由valuelist对象表示的私有集合中管理查询结果。ValueListHandler通常使用数据访问对象创建和操作ValueList集合。当客户端请求结果时,ValueListHandler从原始ValueList创建一个子列表并将其发送到客户端。通常,ValueListHandler管理单个ValueList。但是,如果必须组合和处理多个搜索结果,ValueListHandler可以管理多个ValueList实例。
DataAccessObject - 该ValueListHandler使用DataAccessObject访问数据源,执行查询和检索结果。
ValueList- 值列表是保存查询结果的集合。通常,您可以使用Java Collections API中的List实现,或根据您的需要实现自己的自定义List。
Value - 值表示搜索中的结果数据对象。
实施
考虑一个示例,检索并显示业务对象的列表。在这种情况下,您可以使用值列表处理程序。
ProjectsListHandler类,负责提供Projects列表。此类扩展了ValueListHandler基本抽象类,它提供了值列表处理程序的通用实现。
第1步:创建 ProjectTO 类
<b>public</b> <b>class</b> ProjectTO {
<b>private</b> String projectId;
<b>private</b> String projectName;
<b>private</b> String managerId;
<b>private</b> Date startDate;
<b>private</b> Date endDate;
<b>private</b> <b>boolean</b> started;
<b>private</b> <b>boolean</b> completed;
<b>private</b> <b>boolean</b> accepted;
<b>private</b> Date acceptedDate;
<b>private</b> String customerId;
<b>private</b> String projectDescription;
<b>private</b> String projectStatus;
<b>public</b> String getProjectId() {
<b>return</b> projectId;
}
<b>public</b> <b>void</b> setProjectId(String projectId) {
<b>this</b>.projectId = projectId;
}
<b>public</b> String getProjectName() {
<b>return</b> projectName;
}
<b>public</b> <b>void</b> setProjectName(String projectName) {
<b>this</b>.projectName = projectName;
}
<b>public</b> String getManagerId() {
<b>return</b> managerId;
}
<b>public</b> <b>void</b> setManagerId(String managerId) {
<b>this</b>.managerId = managerId;
}
<b>public</b> Date getStartDate() {
<b>return</b> startDate;
}
<b>public</b> <b>void</b> setStartDate(Date startDate) {
<b>this</b>.startDate = startDate;
}
<b>public</b> Date getEndDate() {
<b>return</b> endDate;
}
<b>public</b> <b>void</b> setEndDate(Date endDate) {
<b>this</b>.endDate = endDate;
}
<b>public</b> <b>boolean</b> isStarted() {
<b>return</b> started;
}
<b>public</b> <b>void</b> setStarted(<b>boolean</b> started) {
<b>this</b>.started = started;
}
<b>public</b> <b>boolean</b> isCompleted() {
<b>return</b> completed;
}
<b>public</b> <b>void</b> setCompleted(<b>boolean</b> completed) {
<b>this</b>.completed = completed;
}
<b>public</b> <b>boolean</b> isAccepted() {
<b>return</b> accepted;
}
<b>public</b> <b>void</b> setAccepted(<b>boolean</b> accepted) {
<b>this</b>.accepted = accepted;
}
<b>public</b> Date getAcceptedDate() {
<b>return</b> acceptedDate;
}
<b>public</b> <b>void</b> setAcceptedDate(Date acceptedDate) {
<b>this</b>.acceptedDate = acceptedDate;
}
<b>public</b> String getCustomerId() {
<b>return</b> customerId;
}
<b>public</b> <b>void</b> setCustomerId(String customerId) {
<b>this</b>.customerId = customerId;
}
<b>public</b> String getProjectDescription() {
<b>return</b> projectDescription;
}
<b>public</b> <b>void</b> setProjectDescription(String projectDescription) {
<b>this</b>.projectDescription = projectDescription;
}
<b>public</b> String getProjectStatus() {
<b>return</b> projectStatus;
}
<b>public</b> <b>void</b> setProjectStatus(String projectStatus) {
<b>this</b>.projectStatus = projectStatus;
}
}
第2步:实现值列表处理程序: ProjectListHandler。
<b>public</b> <b>class</b> ProjectListHandler <b>extends</b> ValueListHandler {
<b>private</b> ProjectDAO dao = <b>new</b> ProjectDAO();
<font><i>// use ProjectTO as a template to determine</i></font><font>
</font><font><i>// search criteria</i></font><font>
<b>private</b> ProjectTO projectCriteria = <b>null</b>;
</font><font><i>// Client creates a ProjectTO instance, sets the </i></font><font>
</font><font><i>// values to use for search criteria and passes </i></font><font>
</font><font><i>// the ProjectTO instance as projectCriteria</i></font><font>
</font><font><i>// to the constructor and to setCriteria() method</i></font><font>
<b>public</b> ProjectListHandler(ProjectTO projectCriteria)
throws Exception {
<b>try</b> {
<b>this</b>.projectCriteria = projectCriteria;
executeSearch();
} <b>catch</b> (Exception e) {
</font><font><i>// Handle exception, throw ListHandlerException</i></font><font>
}
}
<b>public</b> <b>void</b> setCriteria(ProjectTO projectCriteria) {
<b>this</b>.projectCriteria = projectCriteria;
}
</font><font><i>// executes search. Client can invoke this</i></font><font>
</font><font><i>// provided that the search criteria has been</i></font><font>
</font><font><i>// properly set. Used to perform search to refresh</i></font><font>
</font><font><i>// the list with the latest data.</i></font><font>
<b>public</b> <b>void</b> executeSearch()
throws Exception {
<b>try</b> {
<b>if</b> (projectCriteria == <b>null</b>) {
<b>throw</b> <b>new</b> Exception(
</font><font>"Project Criteria required..."</font><font>);
}
List resultsList =
dao.executeSelect(projectCriteria);
setList(resultsList);
} <b>catch</b> (Exception e) {
</font><font><i>// Handle exception, throw ListHandlerException</i></font><font>
}
}
}
</font>
第3步:实现 GenericValueListHandler 类 。
该ValueListHandler是一个通用的迭代类,它提供了迭代功能。
<b>public</b> <b>class</b> ValueListHandler
implements ValueListIterator {
<b>protected</b> List list;
<b>protected</b> ListIterator listIterator;
<b>public</b> ValueListHandler() {}
<b>protected</b> <b>void</b> setList(List list)
throws IteratorException {
<b>this</b>.list = list;
<b>if</b> (list != <b>null</b>)
listIterator = list.listIterator();
<b>else</b>
<b>throw</b> <b>new</b> IteratorException(<font>"List empty"</font><font>);
}
<b>public</b> Collection getList() {
<b>return</b> list;
}
<b>public</b> <b>int</b> getSize() throws IteratorException {
<b>int</b> size = 0;
<b>if</b> (list != <b>null</b>)
size = list.size();
<b>else</b>
<b>throw</b> <b>new</b> IteratorException(</font><font>"No data found"</font><font>); </font><font><i>//No Data</i></font><font>
<b>return</b> size;
}
<b>public</b> Object getCurrentElement()
throws IteratorException {
Object obj = <b>null</b>;
</font><font><i>// Will not advance iterator</i></font><font>
<b>if</b> (list != <b>null</b>) {
<b>int</b> currIndex = listIterator.nextIndex();
obj = list.get(currIndex);
} <b>else</b>
<b>throw</b> <b>new</b> IteratorException(</font><font>""</font><font>);
<b>return</b> obj;
}
<b>public</b> List getPreviousElements(<b>int</b> count)
throws IteratorException {
<b>int</b> i = 0;
Object object = <b>null</b>;
LinkedList list = <b>new</b> LinkedList();
<b>if</b> (listIterator != <b>null</b>) {
<b>while</b> (listIterator.hasPrevious() && (i < count)) {
object = listIterator.previous();
list.add(object);
i++;
}
} </font><font><i>// end if</i></font><font>
<b>else</b>
<b>throw</b> <b>new</b> IteratorException(</font><font>"No data found"</font><font>); </font><font><i>// No data</i></font><font>
<b>return</b> list;
}
<b>public</b> List getNextElements(<b>int</b> count)
throws IteratorException {
<b>int</b> i = 0;
Object object = <b>null</b>;
LinkedList list = <b>new</b> LinkedList();
<b>if</b> (listIterator != <b>null</b>) {
<b>while</b> (listIterator.hasNext() && (i < count)) {
object = listIterator.next();
list.add(object);
i++;
}
} <b>else</b>
<b>throw</b> <b>new</b> IteratorException(</font><font>"No data found"</font><font>); </font><font><i>// No data</i></font><font>
<b>return</b> list;
}
<b>public</b> <b>void</b> resetIndex() throws IteratorException {
<b>if</b> (listIterator != <b>null</b>) {
listIterator = list.listIterator();
} <b>else</b>
<b>throw</b> <b>new</b> IteratorException(</font><font>"No data found"</font><font>); </font><font><i>// No data</i></font><font>
}
}
</font>
第4步:创建 ProjectDAO 类。
<b>public</b> <b>class</b> ProjectDAO {
<b>final</b> <b>private</b> String tableName = <font>"PROJECT"</font><font>;
</font><font><i>// select statement uses fields</i></font><font>
<b>final</b> <b>private</b> String fields = </font><font>"project_id, name,"</font><font> +
</font><font>"project_manager_id, start_date, end_date, "</font><font> +
</font><font>" started, completed, accepted, acceptedDate,"</font><font> +
</font><font>" customer_id, description, status"</font><font>;
</font><font><i>// the methods relevant to the ValueListHandler</i></font><font>
</font><font><i>// are shown here.</i></font><font>
</font><font><i>// See Data Access Object pattern for other details.</i></font><font>
</font><font><i>// ...</i></font><font>
<b>public</b> List < ProjectTO > executeSelect(ProjectTO projCriteria)
throws SQLException {
PreparedStatement stmt = <b>null</b>;
List < ProjectTO > list = <b>null</b>;
Connection con = getConnection();
StringBuffer selectStatement = <b>new</b> StringBuffer();
selectStatement.append(</font><font>"SELECT "</font><font> + fields +
</font><font>" FROM "</font><font> + tableName + </font><font>"where 1=1"</font><font>);
</font><font><i>// append additional conditions to where clause</i></font><font>
</font><font><i>// depending on the values specified in </i></font><font>
</font><font><i>// projCriteria</i></font><font>
<b>if</b> (projCriteria.getProjectId() != <b>null</b>) {
selectStatement.append(</font><font>" AND PROJECT_ID = '"</font><font> +
projCriteria.getProjectId() + </font><font>"'"</font><font>);
}
</font><font><i>// check and add other fields to where clause</i></font><font>
</font><font><i>//...</i></font><font>
<b>try</b> {
stmt = con.prepareStatement(selectStatement.toString());
stmt.setString(1, projCriteria.getProjectId());
ResultSet rs = stmt.executeQuery();
list = prepareResult(rs);
stmt.close();
} <b>finally</b> {
con.close();
}
<b>return</b> list;
}
<b>private</b> Connection getConnection() {
</font><font><i>// TODO Auto-generated method stub</i></font><font>
<b>return</b> <b>null</b>;
}
<b>private</b> List < ProjectTO > prepareResult(ResultSet rs)
throws SQLException {
List < ProjectTO > list = <b>new</b> ArrayList();
<b>while</b> (rs.next()) {
<b>int</b> i = 1;
ProjectTO proj = <b>new</b> ProjectTO();
proj.setProjectName(rs.getString(i++));
proj.setManagerId(rs.getString(i++));
proj.setStartDate(rs.getDate(i++));
proj.setEndDate(rs.getDate(i++));
proj.setStarted(rs.getBoolean(i++));
proj.setCompleted(rs.getBoolean(i++));
proj.setAccepted(rs.getBoolean(i++));
proj.setAcceptedDate(rs.getDate(i++));
proj.setCustomerId(rs.getString(i++));
proj.setProjectDescription(rs.getString(i++));
proj.setProjectStatus(rs.getString(i++));
list.add(proj);
}
<b>return</b> list;
}
</font><font><i>// implement other stuff</i></font><font>
</font><font><i>//...</i></font><font>
}
</font>
第5步:ValueListIterator 接口 。
<b>import</b> java.util.List;
<font><i>//http://www.oracle.com/technetwork/java/valuelisthandler-142464.html</i></font><font>
<b>public</b> <b>interface</b> ValueListIterator {
<b>public</b> <b>int</b> getSize() throws IteratorException;
<b>public</b> Object getCurrentElement() throws IteratorException;
<b>public</b> List getPreviousElements(<b>int</b> count) throws IteratorException;
<b>public</b> List getNextElements(<b>int</b> count) throws IteratorException;
<b>public</b> <b>void</b> resetIndex() throws IteratorException;
</font><font><i>// other common methods as required</i></font><font>
</font><font><i>// ...</i></font><font>
}
</font>
第6步:创建 自定义异常 类。
<b>public</b> <b>class</b> IteratorException <b>extends</b> Exception {
<b>public</b> IteratorException(String message) {
<b>super</b>(message);
}
}
后果