|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/* |
|
|
|
|
* Copyright 2002-2011 the original author or authors. |
|
|
|
|
* Copyright 2002-2012 the original author or authors. |
|
|
|
|
* |
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -16,20 +16,21 @@ |
|
|
|
|
|
|
|
|
|
package org.springframework.jdbc.core; |
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
import java.sql.ResultSet; |
|
|
|
|
import java.sql.SQLException; |
|
|
|
|
import javax.sql.rowset.CachedRowSet; |
|
|
|
|
import javax.sql.rowset.RowSetFactory; |
|
|
|
|
import javax.sql.rowset.RowSetProvider; |
|
|
|
|
|
|
|
|
|
import com.sun.rowset.CachedRowSetImpl; |
|
|
|
|
|
|
|
|
|
import org.springframework.core.JdkVersion; |
|
|
|
|
import org.springframework.jdbc.support.rowset.ResultSetWrappingSqlRowSet; |
|
|
|
|
import org.springframework.jdbc.support.rowset.SqlRowSet; |
|
|
|
|
import org.springframework.util.ReflectionUtils; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* ResultSetExtractor implementation that returns a Spring SqlRowSet |
|
|
|
|
* representation for each given ResultSet. |
|
|
|
|
* {@link ResultSetExtractor} implementation that returns a Spring {@link SqlRowSet} |
|
|
|
|
* representation for each given {@link ResultSet}. |
|
|
|
|
* |
|
|
|
|
* <p>The default implementation uses a standard JDBC CachedRowSet underneath. |
|
|
|
|
* This means that JDBC RowSet support needs to be available at runtime: |
|
|
|
@ -45,20 +46,16 @@ import org.springframework.util.ReflectionUtils; |
|
|
|
|
*/ |
|
|
|
|
public class SqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet> { |
|
|
|
|
|
|
|
|
|
private static Object rowSetFactory = null; |
|
|
|
|
|
|
|
|
|
private static Method createCachedRowSet = null; |
|
|
|
|
private static final CachedRowSetFactory cachedRowSetFactory; |
|
|
|
|
|
|
|
|
|
static { |
|
|
|
|
ClassLoader cl = SqlRowSetResultSetExtractor.class.getClassLoader(); |
|
|
|
|
try { |
|
|
|
|
Class rowSetProviderClass = cl.loadClass("javax.sql.rowset.RowSetProvider"); |
|
|
|
|
Method newFactory = rowSetProviderClass.getMethod("newFactory"); |
|
|
|
|
rowSetFactory = ReflectionUtils.invokeMethod(newFactory, null); |
|
|
|
|
createCachedRowSet = rowSetFactory.getClass().getMethod("createCachedRowSet"); |
|
|
|
|
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_17) { |
|
|
|
|
// using JDBC 4.1 RowSetProvider
|
|
|
|
|
cachedRowSetFactory = new StandardCachedRowSetFactory(); |
|
|
|
|
} |
|
|
|
|
catch (Exception ex) { |
|
|
|
|
else { |
|
|
|
|
// JDBC 4.1 API not available - fall back to Sun CachedRowSetImpl
|
|
|
|
|
cachedRowSetFactory = new SunCachedRowSetFactory(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -88,19 +85,56 @@ public class SqlRowSetResultSetExtractor implements ResultSetExtractor<SqlRowSet |
|
|
|
|
/** |
|
|
|
|
* Create a new CachedRowSet instance, to be populated by |
|
|
|
|
* the <code>createSqlRowSet</code> implementation. |
|
|
|
|
* <p>The default implementation creates a new instance of |
|
|
|
|
* Sun's <code>com.sun.rowset.CachedRowSetImpl</code> class. |
|
|
|
|
* <p>The default implementation uses JDBC 4.1's RowSetProvider |
|
|
|
|
* when running on JDK 7 or higher, falling back to Sun's |
|
|
|
|
* <code>com.sun.rowset.CachedRowSetImpl</code> class on older JDKs. |
|
|
|
|
* @return a new CachedRowSet instance |
|
|
|
|
* @throws SQLException if thrown by JDBC methods |
|
|
|
|
* @see #createSqlRowSet |
|
|
|
|
* @see com.sun.rowset.CachedRowSetImpl |
|
|
|
|
*/ |
|
|
|
|
protected CachedRowSet newCachedRowSet() throws SQLException { |
|
|
|
|
if (createCachedRowSet != null) { |
|
|
|
|
// RowSetProvider.newFactory().createCachedRowSet();
|
|
|
|
|
return (CachedRowSet) ReflectionUtils.invokeJdbcMethod(createCachedRowSet, rowSetFactory); |
|
|
|
|
return cachedRowSetFactory.createCachedRowSet(); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Internal strategy interface for the creation of CachedRowSet instances. |
|
|
|
|
*/ |
|
|
|
|
private interface CachedRowSetFactory { |
|
|
|
|
|
|
|
|
|
CachedRowSet createCachedRowSet() throws SQLException; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Inner class to avoid a hard dependency on JDBC 4.1 RowSetProvider class. |
|
|
|
|
*/ |
|
|
|
|
private static class StandardCachedRowSetFactory implements CachedRowSetFactory { |
|
|
|
|
|
|
|
|
|
private final RowSetFactory rowSetFactory; |
|
|
|
|
|
|
|
|
|
public StandardCachedRowSetFactory() { |
|
|
|
|
try { |
|
|
|
|
this.rowSetFactory = RowSetProvider.newFactory(); |
|
|
|
|
} |
|
|
|
|
catch (SQLException ex) { |
|
|
|
|
throw new IllegalStateException("Cannot create RowSetFactory through RowSetProvider", ex); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public CachedRowSet createCachedRowSet() throws SQLException { |
|
|
|
|
return this.rowSetFactory.createCachedRowSet(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Inner class to avoid a hard dependency on Sun's CachedRowSetImpl class. |
|
|
|
|
*/ |
|
|
|
|
private static class SunCachedRowSetFactory implements CachedRowSetFactory { |
|
|
|
|
|
|
|
|
|
public CachedRowSet createCachedRowSet() throws SQLException { |
|
|
|
|
return new CachedRowSetImpl(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|