【发布时间】:2012-01-20 22:53:06
【问题描述】:
在 JPA 之后使用 Hibernate 3.3.2GA(以及 JBoss 5 中包含的其余 Hibernate 软件包)遇到奇怪的性能问题。
我正在使用 Native Query,并将 SQL 组装成一个准备好的语句。
EntityManager em = getEntityManager(MY_DS);
final Query query = em.createNativeQuery(fullSql, entity.getClass());
SQL 有很多连接,但实际上非常基本,只有一个参数。喜欢:
SELECT field1, field2, field3 FROM entity left join entity2 on... left join entity3 on
WHERE stringId like ?
查询在 MSSQL Studio 上运行不到一秒钟。
如果我添加
query.setParameter(0, "ABC123%");
查询将暂停 9 秒
2012-01-20 14:36:21 - TRACE: - AbstractBatcher.getPreparedStatement:(484) | preparing statement
2012-01-20 14:36:21 - TRACE: - StringType.nullSafeSet:(133) | binding 'ABC123%' to parameter: 1
2012-01-20 14:36:30 - DEBUG: - AbstractBatcher.logOpenResults:(382) | about to open ResultSet (open ResultSets: 0, globally: 0)
但是,如果我只是替换“?”使用值(使其不是准备好的语句,而只是一个直接的 SQL 查询。
fullSql = fullSql.replace("?", "'ABC123%'");
查询将在不到一秒的时间内完成。
我真的希望我们使用 Prepared Statement(参数的输入是从用户数据中提取的)来防止注入攻击。
追踪代码中的慢点,我深入到了 jtds-1.2.2 包中。违规行似乎是 SharedSocket 第 841 行“getIn().readFully(hdrBuf);”不过那里没有什么明显的......
private byte[] readPacket(byte buffer[])
throws IOException {
//
// Read rest of header
try {
getIn().readFully(hdrBuf);
} catch (EOFException e) {
throw new IOException("DB server closed connection.");
}
通过这个堆栈到达...
at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:841)
at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:722)
at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:466)
at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:103)
at net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:88)
at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:3928)
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1045)
at net.sourceforge.jtds.jdbc.TdsCore.microsoftPrepare(TdsCore.java:1178)
at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareSQL(ConnectionJDBC2.java:657)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java:776)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1808)
at org.hibernate.loader.Loader.doQuery(Loader.java:697)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
at org.hibernate.loader.Loader.doList(Loader.java:2228)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
at org.hibernate.loader.Loader.list(Loader.java:2120)
at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312)
at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1722)
at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:175)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)
【问题讨论】:
-
让我将 jtds-1.2.2 添加到技术堆栈中。我已经通过 Hibernate 调试到 JTDS
-
试过jtds-1.2.4,但不喜...
-
切换到 com.microsoft.sqlserver.jdbc.SQLServerDriver 实际上会产生相同的结果......必须看看 SQL Server,也许那里有什么......
标签: java sql hibernate jpa prepared-statement