`
chpn
  • 浏览: 8587 次
  • 来自: ...
社区版块
存档分类
最新评论

使用动态代理实现精简版CachedRowSetImpl

阅读更多
曾经,为了避免“Access restriction” ,打算自动实现一个CachedRowSet  ,于是新建一个类implements CachedRowSet , 没有做其它任何工作,代码已经2千多行了, class文件38K !!!
所以多次因此放弃了。

今天想到用动态代理实现CachedRowSet ,于是只实现其中部分有用的方法,剩余的300多个无用方法不处理。几百行代码就解决问题 ,并且
   支持修改结果集内容,增加结果集的列,
   getXXX( ) 不会字字段不存在出现讨厌的SQLException
   不会因字段使用了别名出现字段不存在的问题

调用方式

ResultSet rs = statement.executeQuery(sql);
CachedRowSet rowSet = SimpleCachedRowSetImpl.newInstance();
rowSet.populate( rs );

ProxyHandler
public    class ProxyHandler implements InvocationHandler {
	private Object concreteClass;

	public ProxyHandler(Object concreteClass) {
		this.concreteClass = concreteClass;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
		try{
			method = concreteClass.getClass().getMethod(method.getName(), method.getParameterTypes() );
			Object object = method.invoke(concreteClass, args);// 普通的Java反射代码,通过反射执行某个类的某方法
			return object;
		}catch(NoSuchMethodException ex){
			if( method.getName().startsWith("set")){
				throw new NoSuchMethodException( ex.getMessage() +", 请使用setObject");
			}
			throw ex;
		}catch( InvocationTargetException ex){
			//抛出原始的错误避免过多的stacktrace
			throw ex.getCause();
		}
	}

}


SimpleCachedRowSetImpl
public class SimpleCachedRowSetImpl implements SimpleRowSet  {
	LinkedList<Object[]> data = new LinkedList<Object[]>();
	TreeMap<String,Integer > fieldNameMap = new TreeMap<String,Integer >( String.CASE_INSENSITIVE_ORDER );
	private static final int FETCHCOUNT = 2000; 
	private int cursor =-1;
	private int rowCount =0;
	private int pageSize = 0;
	private int columnCount =0;
	private ResultSetMetaData meta; 
	private SimpleCachedRowSetImpl(){}
	/**
	 * 创建一个 CachedRowSet 实例
	 * @return
	 */
	public static CachedRowSet newInstance() {
		SimpleCachedRowSetImpl rowset = new SimpleCachedRowSetImpl() ;
		InvocationHandler ih = new ProxyHandler( rowset );
		Class<?>[] interfaces = {CachedRowSet.class,SimpleRowSet.class};
		Object newProxyInstance = Proxy.newProxyInstance( SimpleCachedRowSetImpl.class.getClassLoader()  , interfaces, ih);
	
		return (CachedRowSet)newProxyInstance;
	}
	private void updateMeta(ResultSet rs) throws SQLException{
		ResultSetMetaData oldmeta = rs.getMetaData();
		ResultSetMeta meta = new ResultSetMeta(oldmeta);
		
		columnCount = oldmeta.getColumnCount();
		for(int i=1;i<=columnCount;i++){
			Field field = new Field();
			field.catalogName = oldmeta.getCatalogName( i );
			field.columnClassName = oldmeta.getColumnClassName( i );
			field.columnType = oldmeta.getColumnType( i );
			field.columnLabel = oldmeta.getColumnLabel( i );
			field.columnName = oldmeta.getColumnName( i );
			field.precision  = oldmeta.getPrecision( i );
			field.scale  = oldmeta.getScale( i );
			field.schemaName = oldmeta.getSchemaName( i );
			field.table = oldmeta.getTableName( i );
			meta.addField(field);
		}
		this.meta = meta;
		
	}
	public void populate(ResultSet rs, int start) throws SQLException {
		if( start>-1){
			rs.absolute(start);
			rs.setFetchSize( this.pageSize );
		}else{

			rs.setFetchSize( FETCHCOUNT );
		}
		updateMeta(rs);
		rowCount = 0;
		while(rs.next()){
			Object[] row = new Object[ columnCount ];
			for(int i=1;i<=columnCount ;i++ ){
				row[ i-1 ] = rs.getObject( i );
			}
			data.add( row );
			rowCount++;
			if(start>-1 &&  rowCount> pageSize)
				break;
		} 
		//设置字段序号
		for(int i=1;i<=columnCount;i++){
			String fieldName = meta.getColumnLabel( i ); //使用 as 中的名称
			fieldNameMap.put( fieldName , i -1  ); //从0开始 
		}
		rowCount = data.size();

	}

	public void populate(ResultSet rs ) throws SQLException {
		populate( rs , -1 ); 
	} 
	@Override
	public boolean next() throws SQLException{
		if( cursor<rowCount-1){
			cursor++;
			return true;
		}
		cursor = rowCount;
		return false;
	}
	@Override
	public void beforeFirst() throws SQLException{
		cursor=-1;
	}
	@Override
	public String getString(String key ) throws SQLException{
		Object value = getObject( key );
		if( value==null)
			return null;
		return value.toString();
	}
	@Override
	public String getString(int index ) throws SQLException{
		Object value = getObject( index );
		if( value==null)
			return null;
		return value.toString();
	}
	@Override
	public Object getObject(String key ) throws SQLException{
		int index = getIndex(key); 
		return getObject(index );
	}
	@Override
	public Object getObject(int index ) throws SQLException{
		if( index==-1)
			return null;
		if( index<1 || index> columnCount ){
			throw new SQLException("必须是1-"+columnCount + "之间的数字" );
		} 
		Object[] row = data.get( cursor );
		Object value = row[ index -1  ];
		return value;
	}
 
	

	@Override
	public int getInt(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).intValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).intValue();
		}
		String svalue = value.toString();
		try{
			return Integer.parseInt( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为int类型");
		}
		
	}

	@Override
	public int getInt(String key) throws SQLException {
		int index = getIndex(key); 
		return getInt( index );
		
	}

	@Override
	public long getLong(int index ) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).longValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).longValue();
		}
		String svalue = value.toString();
		try{
			return Long.parseLong( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为long类型");
		}
		
	}

	@Override
	public long getLong(String key) throws SQLException {
		int index = getIndex( key ); 
		return getLong( index );
		
	}
	
	

	@Override
	public float getFloat(String key) throws SQLException {
		int index = getIndex( key ); 
		return getFloat( index );
	}

	@Override
	public float getFloat(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).floatValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).floatValue();
		}
		String svalue = value.toString();
		try{
			return Float.parseFloat( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为float类型");
		}
		
	}

	@Override
	public BigDecimal getBigDecimal(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return null ;
		return ((BigDecimal)value) ;
		
	}

	@Override
	public BigDecimal getBigDecimal(String key) throws SQLException {
		int index = getIndex( key ); 
		return getBigDecimal( index );
		
	}

	@Override
	public double getDouble(int index) throws SQLException {
		Object value = getObject(index);
		if(value==null)
			return 0 ;
		if( value instanceof Number ){
			return ((Number)value).doubleValue();
		}
		if( value instanceof BigDecimal ){
			return ((BigDecimal)value).doubleValue();
		}
		String svalue = value.toString();
		try{
			return Double.parseDouble( svalue );
		}catch(NumberFormatException ex){
			throw new SQLException(svalue+"无法转换为double类型");
		}
		
	}

	@Override
	public double getDouble(String key) throws SQLException {
		int index = getIndex( key ); 
		return getDouble( index );
		
	}
//	@Override
//	public Date getDate(String key) throws SQLException {
//		int index = getIndex( key ); 
//		return getDate( index );
//		
//	}
	private int getIndex(String key){
		Integer index = fieldNameMap.get(key); 
		if( index==null)
			return  -1;
		return index +1;
	}
//	@Override
//	public Date getDate(int index) throws SQLException {
//
//		Object value = getObject(index );
//		if(value==null)
//			return null ;
//		if( value instanceof Date ){
//			return ((Date)value);
//		}
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Date getDate(int index, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Date getDate(String fieldName, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(int index) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(String fieldName) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(int index, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Time getTime(String fieldName, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}

	@Override
	public Timestamp getTimestamp(int index) throws SQLException {

		Object value = getObject(index );
		int type = meta.getColumnType( index );
		if( type== Types.TIMESTAMP ){
			return ((Timestamp)value);
		}
		throw new NotImplementedException();
		
	}

	@Override
	public Timestamp getTimestamp(String fieldName) throws SQLException {
		return getTimestamp( getIndex( fieldName ));
		
	}

//	@Override
//	public Timestamp getTimestamp(int index, Calendar calendar) throws SQLException {
//
//		throw new NotImplementedException();
//		
//	}
//
//	@Override
//	public Timestamp getTimestamp(String fieldName, Calendar calendar) throws SQLException {
//		throw new NotImplementedException();
//		
//	}
//	@Override
//	public Blob getBlob(String fieldName) throws SQLException {
//		throw new NotImplementedException();
//		
//	}

	@Override
	public boolean getBoolean(int index) throws SQLException {
		Object val = getObject(index);
		return new Integer(1).equals(val);
		
	}

	@Override
	public boolean getBoolean(String key) throws SQLException {
		Object val = getObject( key );
		return new Integer(1).equals(val);
		
	}

	@Override
	public byte getByte(int index) throws SQLException {
		Object val = getObject( index );
		if( val==null)
			return 0;
		return (Byte)val;
		
	}

	@Override
	public byte getByte(String key) throws SQLException {
		Object val = getObject( key );
		if( val==null)
			return 0;
		return (Byte)val;
		
	}

//	@Override
//	public byte[] getBytes(int index) throws SQLException {
//		Object val = getObject( index );
//		if( val==null)
//			return null;
//		return (byte[])val;
//		
//	}
//
//	@Override
//	public byte[] getBytes(String fieldName) throws SQLException {
//		return getBytes( getIndex(fieldName));
//		
//	}
	
	public void setPageSize( int pageSize ) throws SQLException{
		this.pageSize = pageSize;
	}
 

	@Override
	public ResultSetMetaData getMetaData() throws SQLException {
		return meta;
		
	}
	@Override
	public void setObject(int colIndex, Object value) throws SQLException  {
		if( colIndex<1){
			throw new SQLException("应从1开始");
		}
		Object[] row = getCurrentRow();
		if( colIndex>row.length){
			row =Arrays.copyOf( row ,  colIndex );
			data.add( cursor , row );
		}
		row[ colIndex -1 ] = value;
	} 
	private Object[] getCurrentRow() { 
		return data.get( cursor );
	}
	@Override
	public void setObject(String field, Object value) throws SQLException  {
		int index = getIndex( field );
		if( index==-1){
			addColumn( field );
			index = getIndex( field );
		}
		//Object[] row = getCurrentRow();
		setObject( index , value );
		
	}
	private void addColumn(String field) {
		fieldNameMap.put( field , fieldNameMap.size() );
		columnCount = fieldNameMap.size();
		
	}
	


}


余下程序见附件
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics