[设计模式]DAO的实现方式探讨_Part I

先说一下我的参考书目:
Core J2EE™ Patterns: Best Practices and Design Strategies, Second Edition
By Deepak Alur, John Crupi, Dan Malks

Publisher : Prentice Hall PTR
Pub Date : June 10, 2003
ISBN : 0-13-142246-4
Pages : 650


关于DAO的部分在
Part 2. J2EE Pattern Catalog
Chapter 8. Integration Tier Patterns
Data Access Object


我没有按顺序说,先说的是后半部分的RowSet Wrapper List Strategy,这部分问题比较少。前半部分我是上周看的,问题比较多,续后再说。
 

 

RowSet Wrapper List Strategy

这种策略用于查询操作,其原理就是把查询的结果集(RowSet),包到一个实现了List接口的类(RowSetWrapperList)中,然后把这个类的实例传给业务类供其使用。

业务类使用的只是一个DAO,一个数据Bean和一个List接口(其实例是RowSetWrapperList,但是业务类并不知道)。

当返回大量的查询结果,而客户只使用其中的一小部分的时候,这种策略更有效率。

RowSet Wrapper List Strategy Class Diagram

关于类图,可以参见:http://blog.csdn.net/fitzwilliam/archive/2006/04/18/668050.aspx


原文:
While the Transfer Object Collection strategy is one way to implement your finder methods, it might prove expensive if the query returns a large set of results and you end up creating a large collection of transfer objects, which are used sparingly by the client. Clients typically search and use the first few result items and discard the rest. When an application is executing a query that returns a large set of results, the RowSet Wrapper List strategy might be more efficient though it requires additional work and adds more complexity.

You do not want to expose the RowSet strategies to external clients of the Data Access Object, regardless of what RowSet implementation you choose to use. It is better to encapsulate all usage of any objects that originate in the java.sql and javax.sql packages inside the Data Access Object. Such encapsulation ensures that the client is not dependent on low-level JDBC interfaces, such as ResultSet or RowSet interfaces. The RowSet Wrapper List strategy internally uses the Read Only RowSet strategy to obtain the query results and wraps the RowSet instance to expose the results in an object-oriented way. The wrapping is done by a custom List implementation that provides the traversal and caching functions to manipulate the RowSet in an object-oriented manner by exposing the data in the rowset as objects.

The advantage of the RowSet Wrapper List strategy is that you create and return Transfer Objects (415) only if necessary; that is, if and when the client needs it. On the other hand, for the Transfer Object Collection strategy, the Data Access Object must create all the Transfer Objects (415) before it returns a Collection to the client.
 
 

这本书列出的例子不太好,有些错误 nu1 ,要是从哪里能下到源代码就好了。 Neutral


关于这种策略的使用方式如下:
public class CustomerDAOClient {


public void search() {

try {

CustomerDAO dao = new CustomerDAO();

CustomerTO criteria = new CustomerTO();

criteria.setZip("94539");

// search for all customers with Zip code 94539

// results to contain a maximum of 1000 matching rows

//这个返回的查询结果就是一个RowSetWrapperList
List searchResults = dao.findCustomersRL(criteria, 0, 999);

int resultSize = searchResults.size();

for (int rowNum=0; rowNum < resultSize; rowNum++) {

CustomerTO customerTO = (CustomerTO)searchResults.get(rowNum);

System.out.println("Customer Row #" + rowNum + " has ");

System.out.println("Customer Id = " + customerTO.getId());

System.out.println("Name = " + customerTO.getName());

}

// get a ListIterator

ListIterator iterator = searchResults.listIterator();

// use the iterator to traverse to next or

// previous row


} catch (Exception e) {

// handle exception

}

}

}


业务代码只是调用DAO和相关的数据类,设置查询条件,然后就可以得到一个List的结果集。其操作和普通的List完全相同。里面的内容就是符合查询条件的数据对象(JavaBean/Pojo)。

RowSetWrapperList的实现
这个类实现了List和Serializable接口,所以可以把其实例赋给一个List引用。
它的实现原理很简单,就是在内部声明了一个RowSet的成员变量,然后把所有List方法的实现映射到这个RowSet的方法上就行了。


示例代码如下:

public class RowSetWrapperList implements List, Serializable {

// variable to hold a RowSet instance
private RowSet rowSet;

public RowSetWrapperList(RowSet rowSet) {

this.rowSet = rowSet;

}

// return the current row as a transfer object
public Object get(int index) {

try {

rowSet.absolute(index);
} catch (SQLException anException) {

// handle exception

}

// create a new transfer object and return
// return TORowMapper.createCustomerTO(this);
//把一条数据库记录(Record)映射成一个数据对象(Pojo)返回给业务层
return TORowMapper.createCustomerTO(rowSet);

}



// Returns a Sub List of the current list.
public List subList(int fromIndex, int toIndex) {

// Create a new RowSet with the required rows
ReadOnlyRowSet roRowSet = new ReadOnlyRowSet();

try {
roRowSet.populate(this.rowSet, fromIndex, toIndex);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

// Create a new RowSetWrapperList instance and
// return it
return new RowSetWrapperList(roRowSet);

}

// Returns an iterator over the elements in this list in

// proper sequence. It is possible to define multiple

// independent iterators for the same RowSetWrapperList

// object.

public Iterator iterator() {

try {

rowSet.beforeFirst();

} catch (SQLException anException) {

System.out.println(

"Error moving RowSet before first row." +

anException);

}

return this.listIterator();

}


// Create a List Iterator that can iterate over the
// rowset
public ListIterator listIterator() {

// ListResultIterator is implemented as an inner class
return new DataRowListIterator();

}


//以前我读TIJ的时候,内部类部分看得就很马马虎虎,感觉不知道在哪里用。这回估计终于有机会用一下了,呵呵。 ya1 kaixin1
// implement the List interface methods
private class DataRowListIterator implements ListIterator {

int currentRow=0;

// sets the rowset cursor to next and returns
// the Transfer object
public Object next() {

// get transfer object for next row of RowSetWrapperList
currentRow++;

// return this.get(currentRow);
return get(currentRow);

}



public Object previous() {

// get transfer object for previous row of
// RowSetWrapperList
currentRow--;

// return this.get(currentRow);
return get(currentRow);


}



// Implement the List Iterator interface
public boolean hasNext() {

// Check the cursor position in the rowSet using
// isLast, isAfterLast, isEmpty methods and
// return true or false accordingly
try {
if (rowSet.next()) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return false;
}


public boolean hasPrevious() {

// Check the cursor position in the rowSet using
// isFirst, isBeforeFirst, isEmpty methods and
// return true or false accordingly
try {
if (rowSet.previous()) {
return true;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return false;

}


// implement other ListIterator methods
public int nextIndex() {
return -1;
}

public int previousIndex() {
return -1;
}


// optional methods not implemented throw
// UnsupportedException
public void set(Object o) {

throw new UnsupportedOperationException();

}

public void add(Object o) {

throw new UnsupportedOperationException();

}



public void remove() {
// TODO Auto-generated method stub

}
}


}

TORowMapper的示例代码:

public class TORowMapper {



// create Customer TO

public static CustomerTO createCustomerTO(RowSet rowSet) {

CustomerTO to = new CustomerTO();

to.setId(getString(rowSet, 0));

to.setName(getString(rowSet, 1));
return to;

}


... ....
// Other primitive getXXX methods for all required

// data types

}




CustomerDAO示例代码:
public class CustomerDAO {

。。。 。。。

public List findCustomersRL(CustomerTO cust, int startAtRow, int howManyRows)
throws Exception {

// create the search SQL string
String searchSQLString = getSearchSQLString(cust);

// execute the search

return executeSearch(searchSQLString, startAtRow, howManyRows);

}

private List executeSearch(String searchSQLString, int startAtRow,
int howManyRows) throws Exception {
RowSetWrapperList results = null;

try {

RowSet rowSet = getRORowSet(searchSQLString, startAtRow,
howManyRows);

results = new RowSetWrapperList(rowSet);
} catch (Exception ex) {

throw new Exception(ex);

}

return results;

}
。。。 。。。
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值