问题描述
我的环境:面向企业 Java 开发人员的 Eclipse IDE,版本:2019-09 R (4.13.0)
My environment: Eclipse IDE for Enterprise Java Developers, Version: 2019-09 R (4.13.0)
服务器:WildFly 13.0.0.Final
Server: WildFly 13.0.0.Final
我正在尝试将数据批量上传到 Sql Server,下面的代码在我的 WildFly 服务器中完美运行,但在具有相同版本的 Wildfly 服务器的客户端服务器机器上失败,java.lang.ClassCastException: org.jboss.jca.adapters.jdbc.jdk8.WrappedPreparedStatementJDK8 在下面的语句中不能强制转换为 com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement:
I'm trying to bulk upload the data to Sql Server and the code below works perfectly in my WildFly server with same version but fails in the client's server machine with same wildfly server with java.lang.ClassCastException: org.jboss.jca.adapters.jdbc.jdk8.WrappedPreparedStatementJDK8 cannot be cast to com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement in the statement below:
SQLServerPreparedStatement pStmt = (SQLServerPreparedStatement) con.prepareStatement(execStoredProc);
完整代码如下:
import com.microsoft.sqlserver.jdbc.SQLServerDataTable;
import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement;
import java.sql.*;
import java.util.ArrayList;
public class DatabaseExtended extends Database {
public DatabaseExtended(String assetDisposition, String assetDisposition_ds) {
super(assetDisposition, assetDisposition_ds);
// TODO Auto-generated constructor stub
}
public Object executeEstimateStructured(int iClientID, SQLServerDataTable sourceDataTable) {
//boolean rs = false;
ArrayList<String[]> lst = new ArrayList<String[]>();
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = DriverManager.getConnection(super.connectionUrl);
Statement stmt = con.createStatement();
String execStoredProc = "EXEC UploadEstimate ?,?";
SQLServerPreparedStatement pStmt = (SQLServerPreparedStatement) con.prepareStatement(execStoredProc);//<--Exception here
pStmt.setInt(1, iClientID);
pStmt.setStructured(2, "dbo.UT_Estimate", sourceDataTable);
ResultSet rs = pStmt.executeQuery();
int columnCount = rs.getMetaData().getColumnCount();
while (rs.next()) {
int i = 1;
String[] cols = new String[columnCount];
while (i <= columnCount) {
cols[i - 1] = rs.getString(i++);
}
lst.add(cols);
}
con.close();
}
catch (SQLException e) {
e.printStackTrace();
}
return lst;
}
}
在谷歌搜索这个异常时,我遇到了这个链接,它谈到了将 jboss-deployment-structure.xml 文件放在WEB-INF 文件夹,其中包含提到的依赖项.下面是我的 jboss-deployment-structure.xml 文件
On googling on this exception, I came across this link that talks about placing the jboss-deployment-structure.xml file in WEB-INF folder with the dependencies mentioned. Below is my jboss-deployment-structure.xml file
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<dependencies>
<module name="org.jboss.ironjacamar.jdbcadapters" slot="main"/>
<module name="com.microsoft.sqlserver" slot="main"/>
</dependencies>
</deployment>
</jboss-deployment-structure>
我在构建路径和部署结构中引用了 mssql-jdbc-7.4.1.jre8.jar 文件,以便在 web-inf/lib 文件夹下添加依赖项.
I have referenced mssql-jdbc-7.4.1.jre8.jar file in the build path as well as in the Deployment structure so that the dependency is added under web-inf/lib folder.
现在将这个 jboss-deployment-structure.xml 文件放在 web-inf 文件夹中并部署 war 文件后,我得到以下异常.我不确定我的 jboss-deployment-structure.xml 是否正确以及它是否放置在正确的文件夹中.你能帮忙吗?
Now after placing this jboss-deployment-structure.xml file in the web-inf folder and deploying the war file, I get the following exception. I'm not sure if my jboss-deployment-structure.xml is correct and that it is placed in the correct folder or not. Can you please help?
ERROR [io.undertow.request] (default task-5) UT005023: Exception handling request to /AD/control/UploadEstimates: java.lang.IllegalAccessError: tried to access class com.microsoft.sqlserver.jdbc.Util from class com.microsoft.sqlserver.jdbc.SQLServerDataTable
at com.microsoft.sqlserver.jdbc.SQLServerDataTable.addColumnMetadata(SQLServerDataTable.java:83)
at com.MyClient.AD.util.UploadEstimateUT.start(UploadEstimateUT.java:66)
at com.MyClient.AD.util.UploadEstimates.doPost(UploadEstimates.java:107)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1514)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:360)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1985)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1487)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1378)
at java.lang.Thread.run(Thread.java:748)
2020 年 3 月 16 日更新
这是我使用批处理语句更新的代码:
Update 16-Mar-2020
This is my updated code using batch statements:
public String executeInboundEstimateBatchedStoredProc(int iClientID, SQLServerDataTable sourceDataTable) {
String message="";
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = super.getConnection();
String execStoredProc = "EXEC UploadEstimate ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?";
PreparedStatement pStmt = con.prepareStatement(execStoredProc);
Iterator<Entry<Integer, Object[]>> itr1 = sourceDataTable.getIterator();
while (itr1.hasNext()) {
Object[] lst= itr1.next().getValue();
int numColumns = lst.length;
pStmt.setInt(1, iClientID);
for (int i = 0; i < numColumns; i++) {
pStmt.setString(i+2, lst[i].toString());
}
// add single insert query
pStmt.addBatch();
}
// Execute batch
int[] counts = pStmt.executeBatch();
if (pStmt != null) {
pStmt.close();
}
if (con != null) {
con.close();
}
}
// Handle any errors that may have occurred.
catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
message=e.getMessage();
}
return message;
}
推荐答案
你不应该检查连接对象的准备好的语句的返回类型.依赖于平台的底层驱动程序可以提供他们自己的预准备语句 INTERFACE 的实现,这与用户无关.你应该只使用接口提供的公共方法,而不是进一步挖掘.在您的情况下,您没有错误,只需将您的语句转换为通用类型即可.PreparedStatement pStm=con.prepareStatememt(execStoredProc) 如果你处理一个我从你的 execStoredProc 中假设的过程,然后使用 con.prepareCall() 并存储在 Callable Statement 类型中
U should never have to check the return type of the prepared statement of an connection object. The underlying driver which is platform dependent can provide their own implementation of the prepared statement INTERFACE which is not of the users concern. U should only work with the public methods provided by the interface and not dig any further. In ur case u don't have an error just cast ur statement to the general type. PreparedStatement pStm=con.prepareStatememt(execStoredProc) if ur dealing with an procedure which I assume from your execStoredProc then use con.prepareCall() and store in an Callable Statement type
这篇关于我收到 ClassCastException:WrappedPreparedStatementJDK8 无法转换为 SQLServerPreparedStatement的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!