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

使用动态代理实现精简版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();
		
	}
	


}


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

相关推荐

    VB6.0精简版

    在精简版中,VB6.0的窗体设计工具依然可用,开发者可以轻松创建各种用户界面,包括菜单、按钮、文本框、列表框等控件,通过设置控件属性和编写事件处理代码,实现交互式的应用程序。此外,VB6.0的集成开发环境(IDE...

    超级精简版的jre

    标题中的"超级精简版的jre"指的是对标准JRE进行优化和裁剪,移除了不必要的组件和服务,以实现更小的体积、更快的启动速度以及更低的资源消耗。 精简版JRE通常是为了满足特定应用场景的需求,比如嵌入式设备、低...

    精简版绿色Matlab

    【Matlab精简版】是针对那些只需要使用Matlab基础功能的用户设计的,它相比标准版具有更小的体积,降低了对系统资源的占用,是轻量级的计算工具。Matlab是一款强大的数学计算软件,广泛应用于工程计算、数据分析、...

    CAJViewer绿色精简版

    精简版则意味着在保留核心功能的同时,去除了不必要的组件,以实现更小的体积和更快的启动速度。 在使用CAJViewer绿色精简版时,用户需确保自己的电脑系统环境满足软件运行的基本要求,例如兼容的操作系统版本和...

    Borland 3.1 精简版

    在实际应用中,Borland 3.1精简版的使用步骤大致如下: 1. 创建项目:利用IDE创建一个新的工程,设置好编译选项,包括目标架构和优化级别。 2. 添加源代码:将uCOSII的源代码添加到项目中,这通常包括内核文件、任务...

    超级精简版WINXP系统(体积仅98MB)

    1. **体积减小**:原版Windows XP的安装文件通常在650MB以上,而超级精简版将其压缩至98MB,通过删除非必要的组件和服务实现了大幅瘦身。 2. **启动快速**:由于系统组件减少,启动时间显著缩短,对于需要快速启动的...

    Win2003精简版.7z

    此外,出于安全考虑,不建议在生产环境中直接使用未授权的精简版系统镜像,而是应该选择官方渠道获取授权的完整版系统,以确保系统更新和安全性。 总的来说,"Win2003精简版.7z"是一个便于学习和测试的Windows ...

    BORLAND3.1精简版使用流程

    BORLAND3.1精简版使用流程,安装教程进行设置,就会轻松实用BORLAND3.1精简版了

    nimsql2000_迷你SQL_sql2000精简版_精简版SQL2000_精简型sql2000_

    使用时,用户可以通过SQL Server Management Studio Express(或其精简版)进行数据库的管理和操作。 总的来说,SQL Server 2000 精简版虽然功能有所缩减,但仍然提供了可靠且基础的数据库服务,是初学者和小型企业...

    visio2003 精简版

    4. **数据链接**:Visio 2003支持数据链接功能,可以将图表与外部数据源(如数据库或Excel表格)关联,实时更新图表信息,实现动态可视化。 5. **智能图表**:具备自动布局和连接线调整功能,能帮助用户更高效地...

    MySQL5.7精简版.zip

    MySQL5.7精简版是一款轻量级但功能强大的关系型数据库管理系统,它在MySQL5.7的基础上进行了优化,去除了部分非核心组件,以适应更广泛的使用场景,特别是对于那些对系统资源有限制或者不需要全部功能的用户。...

    PADS9.5三合一精简版

    **PADS 9.5三合一精简版详解** PADS(PowerPCB)是一款广泛应用于电子设计自动化领域的软件,由 Mentor Graphics 公司开发,主要用于电路板设计、布局布线以及PCB(印刷电路板)设计。在这个特定的版本——"PADS ...

    PADS9.3精简版100多M

    标题中的“PADS9.3精简版100多M”指的是PADS Logic, Layout,和PCB Router三合一的精简版本,这是一款强大的电子设计...通过阅读提供的文本文件,用户可以了解如何正确安装和使用这个精简版软件,进一步提高设计效率。

    jquery精简版jquery-small.js

    jquery 精简版 jquery 精简版 jquery 精简版jquery 精简版 jquery 精简版 jquery 精简版 jquery 精简版

    精简版jre.zip 64位 1.8.0压缩后才20M

    - 开发者测试环境:开发者在调试和测试Java桌面应用时,若不需要开发工具,使用此精简版JRE足够。 - 教学环境:对于初学者,无需安装庞大的Java开发工具包(JDK),仅安装这个JRE即可运行学习项目。 - 低配置设备...

    AD6 精简版 免安装

    标题 "AD6 精简版 免安装" 指的是Altium Designer的一个特别版本,这个版本经过了优化和裁剪,目的是提供一个轻量级的解决方案,无需正式安装即可使用。AD6,全称Altium Designer 6,是一款业界广泛使用的电子设计...

    SQL Server2000 SP4企业版精简版8M.rar

    这个"SQL Server 2000 SP4企业版精简版8M.rar"是一个压缩包,其中包含了SQL Server 2000的企业版精简版安装程序——"SQL Server 2000 SP4企业版精简版8M.exe"。"SP4"指的是Service Pack 4,这是SQL Server 2000的...

    VB精简版 免安装

    "VB精简版 免安装"通常指的是一个经过优化、体积较小的版本,它无需进行完整的安装过程,可以直接运行,方便用户快速使用或在有限的系统资源下操作。 在VB精简版中,微软可能移除了部分非核心功能,例如某些高级的...

Global site tag (gtag.js) - Google Analytics