Java 将NewProxyConnection强制转换为C3P0ProxyConnection时发生ClassCastException

Java 将NewProxyConnection强制转换为C3P0ProxyConnection时发生ClassCastException,java,oracle,hibernate,oracle11g,c3p0,Java,Oracle,Hibernate,Oracle11g,C3p0,在我们的应用程序中,我们使用hibernate配置了c3p0池连接。使用数组类型的输入调用存储过程 我必须通过移除所有包装来获得底层连接。然而在这种情况下,当我尝试获取C3P0ProxyConnection类时,我总是得到一个ClassCastException 有没有一种简单的方法来调用具有复杂输入(如数组)的存储过程? 在下面的代码中,我打印了一些类加载器信息,以查看铸造类是否由不同的类加载器加载 类加载器。但是连接类位置为null,因此必须由引导类装入器装入。这可能是问题所在吗 我附加了一

在我们的应用程序中,我们使用hibernate配置了c3p0池连接。使用数组类型的输入调用存储过程 我必须通过移除所有包装来获得底层连接。然而在这种情况下,当我尝试获取C3P0ProxyConnection类时,我总是得到一个ClassCastException

有没有一种简单的方法来调用具有复杂输入(如数组)的存储过程? 在下面的代码中,我打印了一些类加载器信息,以查看铸造类是否由不同的类加载器加载 类加载器。但是连接类位置为null,因此必须由引导类装入器装入。这可能是问题所在吗

我附加了一个来自hinernate会话工厂的实际连接对象的快照

private List<InvoicePrintDetailsDTO> getSelectedInvoiceDetailsToPrint(List<Integer> selectedInvoiceIds) {
    Currency defaultCurrency = DAOInstanceFactory.getInstance().getCurrencyDAO().loadCurrencyByCurrencyCode("LKR");
    List<InvoicePrintDetailsDTO> listOfInvoicesToPrint = Collections.emptyList();
    Session session = DAOInstanceFactory.getInstance().getSessionFactory().getCurrentSession();
    Connection connection = session.connection();

    try {
        Object[] invoiceIds = selectedInvoiceIds.toArray();
        Array invoiceIdsARRAY = getSqlArray(invoiceIds,"SELECTEDINVOICEIDS",connection);

        String query = "{call GETINVOICEPRINTDATA(?,?,?,?)}";
        CallableStatement  ocs = connection.prepareCall(query);
        ocs.setArray(1, invoiceIdsARRAY);
        ocs.setInt(2, defaultCurrency != null ? defaultCurrency.getId() : 0);
        ocs.setInt(3, 1000);
        ocs.registerOutParameter(4, OracleTypes.ARRAY,"INVOICEPRINTINVOICES");
        ocs.executeUpdate();

        Array resultsAsArray = ocs.getArray(8);
        Map<String,Class<?>> resultsAsMap = connection.getTypeMap();
        resultsAsMap.put("INVOICEPRINTINVOICEINFO", Class.forName("com.xxxx.xxxxx.business.utill.InvoicePrintDetailsDTO"));

        if(resultsAsArray!=null) {
            Object[] values = (Object[]) resultsAsArray.getArray();

            if(values != null && values.length > 0) {
                listOfInvoicesToPrint = new ArrayList<InvoicePrintDetailsDTO>();
                for (int i=0; i < values.length; i++){
                    InvoicePrintDetailsDTO obj = (InvoicePrintDetailsDTO)values[i];
                    listOfInvoicesToPrint.add(obj);
                }
            }
        }
    } catch (Exception exception) {
        logger.error(ERROR_OCCOURED_WHILE_GENERATING_INVOICE_PRINT, exception);
    } finally {
        try {
            if(connection != null && !connection.isClosed()){
                connection.close();
            }
        } catch (SQLException sqlException) {
            logger.error(ERROR_OCCOURED_WHILE_GENERATING_INVOICE_PRINT, sqlException);
        }
    }
    return listOfInvoicesToPrint;
}

private Array getSqlArray(Object[] data, String sqlTypeName, Connection connection) throws SQLException {
    Array array = null;

    Class<? extends Connection> connectionClass = connection.getClass();
    ClassLoader connectionClassLoader = connectionClass.getClassLoader();
    System.out.println("Connection class loader is :"+connectionClassLoader.toString());
    System.out.println("Connection class location :"+connectionClass.getResource('/' + connectionClass.getName().replace('.', '/') + ".class"));

    Class<C3P0ProxyConnection> c3P0ProxyConnectionClass = C3P0ProxyConnection.class;
    ClassLoader proxyConnectionLoader = c3P0ProxyConnectionClass.getClassLoader();
    System.out.println("Proxy Connection class loader is :"+proxyConnectionLoader.toString());
    System.out.println("C3P0ProxyConnection class location :"+c3P0ProxyConnectionClass.getResource('/' + c3P0ProxyConnectionClass.getName().replace('.', '/') + ".class"));

    Class<NewProxyConnection> newProxyConnectionClass = NewProxyConnection.class;
    ClassLoader newProxyConnectionLoader = newProxyConnectionClass.getClassLoader();
    System.out.println("New Proxy Connection class loader is :"+newProxyConnectionLoader.toString());
    System.out.println("NewProxyConnection class location :"+newProxyConnectionClass.getResource('/' + newProxyConnectionClass.getName().replace('.', '/') + ".class"));

    C3P0ProxyConnection proxyValue = (C3P0ProxyConnection) connection;

    if (connection instanceof C3P0ProxyConnection) {
        C3P0ProxyConnection proxy = (C3P0ProxyConnection) connection;
        try {
            Method m = Connection.class.getMethod("createArrayOf", String.class, Object[].class);
            Object[] arrayOfArguments = { sqlTypeName, data };
            array = (Array) proxy.rawConnectionOperation(m, C3P0ProxyConnection.RAW_CONNECTION, arrayOfArguments);
        } catch (Exception exception) {
            logger.error("Error calling createArrayOf", exception);
            throw new SQLException(exception);
        }
    }
    return array;
}
因此,有几件事:

$Proxy315不是C3P0PROXY连接。它是一个由hibernate生成的动态代理,它围绕。嵌入其中的可能是C3P0ProxyConnection。如果确实需要,可以使用静态方法借用ConnectionProxy.getWrappedConnection。。。展开到可能是c3p0 NewProxyConnection的对象。您还可以使用JDBC连接标准方法。 但你可能不想做这些。数组方法现在是标准的JDBC,使用它们不需要打开到本机连接。只需跳过所有的幻想,即跳过c3p0原始连接操作,以及。
如果您使用的是非常旧版本的hibernate,并且动态代理实现的是旧版本的连接,那么您可能必须获得包装连接的唯一原因就是。如果是这种情况,请尝试借用ConnectionProxy.getWrappedConnection。。。在你的演员面前。由于您正在进行大量打印调试,请打印您获得的连接,以确保它符合您的预期。

是@Steve Waldman您完全正确。 我得到的代理不是C3P0ProxyConnection。因此,没有简单的方法可以将其转换为C3P0ProxyConnection并使用C3P0RAW连接操作。 但是,我尝试在从hibernate会话获得的连接上直接调用createArrayOf,但由于相同的强制转换异常而失败。 根据这一点,我认为Oracle不支持createArrayOf方法。 顺便说一句,我们正在使用hibernate-3.2.6.ga.jar

我注意到的另一件重要的事情是,当我从我的应用程序deploymentWEB INF/lib中删除ojdbc6.jar并让它从JBOSS libs加载时,我在那里配置了C3P0PooledDataSource, ClassCastException消失了

笔记 我创建了Oracle对象类型来存储发票ID,并更改了最初为此输入创建的对象类型的名称

以下是我最终是如何做到的。
Steve如果您觉得这个答案不准确,请随时改进或删除它。

这是一个代理,它可能只实现连接接口。您是否知道如何从代理获取实现?或者使用数组等复杂输入调用存储过程的任何其他方法?我不知道为什么尝试使用c3p0池连接创建C3P0ProxyConnection类型的变量,我觉得这是通过rawConnectionOperation方法调用行操作的唯一方法您需要展开它,如何做取决于您使用的版本,但是看看如何做到这一点,这里有很多答案。你说得对。非常感谢你。我会用我的方式发布一个答案。
20:36:53,622 INFO  [STDOUT] Connection class loader is :WebappClassLoader
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
java.net.FactoryURLClassLoader@21bdbf51
20:36:53,623 INFO  [STDOUT] Connection class location :null
20:36:53,624 INFO  [STDOUT] Proxy Connection class loader is :WebappClassLoader
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
java.net.FactoryURLClassLoader@21bdbf51
20:36:53,624 INFO  [STDOUT] C3P0ProxyConnection class location :jar:file:/D:/jboss-4.2.2.GA/server/default/deploy/xxxx.war/WEB-INF/lib/c3p0-0.9.5.2.jar!/com/mchange/v2/c3p0/C3P0ProxyConnection.class
20:36:53,625 INFO  [STDOUT] New Proxy Connection class loader is :WebappClassLoader
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
java.net.FactoryURLClassLoader@21bdbf51
20:36:53,626 INFO  [STDOUT] NewProxyConnection class location :jar:file:/D:/jboss-4.2.2.GA/server/default/deploy/xxxx.war/WEB-INF/lib/c3p0-0.9.5.2.jar!/com/mchange/v2/c3p0/impl/NewProxyConnection.class
20:36:53,631 INFO  [STDOUT] ERROR [http-10.10.10.117-8080-6] (InvoicePDFBody.java:316) - Error occoured while generating invoice print.
java.lang.ClassCastException: $Proxy315 cannot be cast to com.mchange.v2.c3p0.C3P0ProxyConnection
    at com.xxxx.xxxx.print.handlers.InvoicePDFBody.getSqlArray(InvoicePDFBody.java:358)
    at com.xxxx.xxxx.print.handlers.InvoicePDFBody.getSelectedInvoiceDetailsToPrint(InvoicePDFBody.java:290)
    at com.xxxx.xxxx.print.handlers.InvoicePDFBody.buildPdfDocument(InvoicePDFBody.java:413)
    at com.xxxx.document.print.controller.InvoicePDFGenerator.buildPdfDocument(InvoicePDFGenerator.java:19)
    at org.springframework.web.servlet.view.document.AbstractPdfView.renderMergedOutputModel(AbstractPdfView.java:78)
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:264)
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.extremecomponents.table.filter.AbstractExportFilter.doFilter(AbstractExportFilter.java:49)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.custom.spring.plugin.AuthenticationFilter.doFilter(AuthenticationFilter.java:39)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.custom.spring.plugin.RoleBasedAccessFilterForInviocePrint.doFilter(RoleBasedAccessFilterForInviocePrint.java:60)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at com.custom.spring.plugin.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:199)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:179)
    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:262)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
    at java.lang.Thread.run(Thread.java:662)
private ARRAY getSqlArray(List<Integer> listOfInvoiceIds, Connection connection) throws SQLException {
    OracleConnection oracleConnection = connection.unwrap(OracleConnection.class);
    StructDescriptor selectedInvoiceInfoDescriptior = StructDescriptor.createDescriptor("SELECTEDINVOICEINFO", oracleConnection);
    List<STRUCT> listOfInvoices = new ArrayList<STRUCT>();

    for (Object invoiceIdObject : listOfInvoiceIds) {
        listOfInvoices.add(new STRUCT(selectedInvoiceInfoDescriptior,oracleConnection,new Object[] {invoiceIdObject}));
    }
    return new ARRAY(ArrayDescriptor.createDescriptor("SELECTEDINVOICES",oracleConnection),oracleConnection,listOfInvoices.toArray());
}