我在AsyncTask
中使用jtds 1.3.0进行Microsoft SQL 2008连接。我的doInBackground()
方法返回一个ResultSet
对象。然后我从ResultSet
方法中的onPostExecute()
读取行。通常我的查询应返回4701行。但是我得到第58至第60行的NetworkOnMainThreadException然后连接停止(我能够读取前60行)。我的原始查询是:
SELECT ID,TITLE,CODE FROM COMPANIES
为了进行实验,我尝试过:
SELECT TOP 50 ID,TITLE,CODE FROM COMPANIES --No problem.
SELECT TOP 100 ID,TITLE,CODE FROM COMPANIES --Throws exception.
logcat输出:
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1166)
at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163)
at libcore.io.IoBridge.recvfrom(IoBridge.java:506)
at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
at libcore.io.Streams.readFully(Streams.java:81)
at java.io.DataInputStream.readFully(DataInputStream.java:99)
at java.io.DataInputStream.readFully(DataInputStream.java:95)
at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:881)
at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:762)
at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:477)
at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:114)
at net.sourceforge.jtds.jdbc.ResponseStream.readInt(ResponseStream.java:329)
at net.sourceforge.jtds.jdbc.TdsData.readData(TdsData.java:728)
at net.sourceforge.jtds.jdbc.TdsCore.tdsRowToken(TdsCore.java:3080)
at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2347)
at net.sourceforge.jtds.jdbc.TdsCore.getNextRow(TdsCore.java:772)
at net.sourceforge.jtds.jdbc.JtdsResultSet.next(JtdsResultSet.java:611)
at com.example.sql.FragmentMain$1.onPostExecute(FragmentMain.java:69)
at com.example.sql.FragmentMain$1.onPostExecute(FragmentMain.java:52)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5602)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
at dalvik.system.NativeStart.main(Native Method)
生成错误的代码:
new DatabaseTask(
((ActivityMain) getActivity()).getConnectionURL()
, getString(R.string.query_all_companies))
{
@Override
protected void onPreExecute()
{
super.onPreExecute();
if (D) Log.d(TAG, "Querying the companies..");
}
@Override
protected void onPostExecute(ResultSet resultSet)
{
super.onPostExecute(resultSet);
try
{
if (resultSet != null)
{
int i = 0;
while (resultSet.next()) /*while loop causes error according to logcat.*/
{
if (D) Log.i(TAG,i++);
}
}
} catch (SQLException e)
{
e.printStackTrace();
}
}
}.execute();
最后,我在gradle文件中的sdk设置:
minSdkVersion 14
targetSdkVersion 22
和依赖项:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile files('libs/jtds-1.3.0.jar')}
为了简单起见,我没有包含我的AsyncTask
课程。基本上我打开了一个连接,并在Connection.execute()
中拨打doInBackground()
。如果有人想重现错误,我可以编辑我的帖子。
谢谢
这是我的AsyncTask
课程。
public class DatabaseTask extends AsyncTask<Object,String,ResultSet>
{
private final boolean D = true;
private final String TAG = "DatabaseTask";
private String url;
private String sqlStatement;
public DatabaseTask(String url, String sqlStatement)
{
this.url = url;
this.sqlStatement = sqlStatement;
}
private void addParams(PreparedStatement preparedStatement,Object... params) throws SQLException
{
if (params != null && params.length > 0)
{
for (int i = 0; i < params.length; i++)
{
Object param = params[i];
if (param instanceof String)
{
preparedStatement.setString(i+1, param.toString());
if (D) Log.d(TAG, "String parameter \'" + param + "\' added.");
} else if (param instanceof Integer)
{
preparedStatement.setInt(i+1, (Integer) param);
if (D) Log.d(TAG, "Integer parameter \'" + param + "\' added.");
} else if (param instanceof Double)
{
preparedStatement.setDouble(i+1, (Double) param);
if (D) Log.d(TAG, "Double parameter \'" + param + "\' added.");
} else if (param instanceof BigDecimal)
{
preparedStatement.setBigDecimal(i+1, (BigDecimal) param);
if (D) Log.d(TAG, "BigDecimal parameter \'" + param + "\' added.");
}
else
if (D) Log.e(TAG,"SQL parameter type is not supported.");
}
}
}
@Override
protected ResultSet doInBackground(Object... params)
{
try
{
Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
Connection connection;
connection = DriverManager.getConnection(url,
ActivityMain.DB_USER_NAME,
ActivityMain.DB_PASSWORD);
if (connection != null)
{
if (D) Log.d(TAG, "Connection successful.");
connection.setAutoCommit(true);
PreparedStatement preparedStatement = connection.prepareStatement(sqlStatement);
addParams(preparedStatement, params);
preparedStatement.execute();
return preparedStatement.getResultSet();
}
else
{
if (D) Log.d(TAG, "Connection failed.");
}
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (InstantiationException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
} catch (SQLException e)
{
if (D) Log.e(TAG,e.getMessage());
e.printStackTrace();
}
return null;
}
}
答案 0 :(得分:0)
我终于找到了解决方案。从this链接我看到,如果超过ResultSet
的提取大小,它会尝试连接到Internet并获取下一部分数据。因此,使用ResultSet.setFetchSize(cacheSize)
或将ResultSet.next()
方法调用移至AsyncTask
可以解决问题。