Maven モジュールで構成される Java EE 7 EAR アプリケーションに取り組んでいます。LAN上の別のサーバーにあるOracle 11データベースへのデータベース呼び出しを行います。Ubuntu 12.04 で実行されている Glassfish 4.0.1-b03 にデプロイしています。Oracle から最新の OJDBC6.jar を取得しました。http://docs.oracle.com/cd/E18930_01/html/821-2418/gbxjh.htmlに従って、ojdbc6.jar を に入れましたdomain1/lib/ext
。
SQLDeveloper を使用して、ほぼ同じクエリでデータベースにクエリを実行すると、10 ミリ秒かかります。JPA/JPQL を介した同じクエリは、構成に応じて 0.5 ~ 3 分かかるため、これをより合理的なものにしようとしています。
クエリは 40 行を返すため、ページネーションは役に立ちません。
返されるデータを監視するために Wireshark を使用していますが、かかる時間はすべてデータベース上にあります。問題は、送信されるクエリにあるはずです。
次のようにロギングをオンにしました。EclipseLinkがDBに送信しているクエリであると思われるものを示しています。
<property name="eclipselink.logging.level" value="FINEST" />
<property name="eclipselink.logging.level.sql" value="FINEST" />
構成 1
persistence.xml には以下が含まれます。
<property name="eclipselink.target-database" value="Oracle"/>
ログのクエリ:
SELECT ALERT_P, CNT, COLOUR, DFROMUIDCNT, FROMUIDCNT, IS_PRIORITYWORD, IS_STOPWORD, N, NIJ, NRTCNT, PJ, RTCCNT, RTCNT, TIME_STAMP, STEM, TWEETS FROM ALL_ALERTS WHERE (TIME_STAMP BETWEEN ? AND ?) ORDER BY TIME_STAMP, STEM
かかった時間 25秒
構成 2
以下を含むように persistence.xml を変更します。
<property name="eclipselink.target-database" value="Oracle11"/>
例外があります:
org.glassfish.deployment.common.DeploymentException: java.lang.NoSuchFieldError: HINT
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.deploy(EntityManagerSetupImpl.java:765)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.getAbstractSession(EntityManagerFactoryDelegate.java:204)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate.createEntityManagerImpl(EntityManagerFactoryDelegate.java:304)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:336)
at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:302)
at org.glassfish.persistence.jpa.JPADeployer$2.visitPUD(JPADeployer.java:451)
at org.glassfish.persistence.jpa.JPADeployer$PersistenceUnitDescriptorIterator.iteratePUDs(JPADeployer.java:510)
at org.glassfish.persistence.jpa.JPADeployer.iterateInitializedPUsAtApplicationPrepare(JPADeployer.java:492)
at org.glassfish.persistence.jpa.JPADeployer.event(JPADeployer.java:395)
at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:131)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:484)
at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:539)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:535)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:356)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:534)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:565)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$3.run(CommandRunnerImpl.java:557)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:356)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:556)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1464)
at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1300(CommandRunnerImpl.java:109)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1846)
at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1722)
at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
at org.glassfish.grizzly.http.server.StaticHttpHandlerBase.service(StaticHttpHandlerBase.java:189)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:496)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:175)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:187)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:837)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:722)
http://en.wikibooks.org/wiki/Java_Persistence/Oracleによると、Oracle11 を使用する必要があります。なぜこの例外が発生するのかわかりません。 この問題について何か考えはありますか?
構成 3
eclipselink.target-database
persistence.xml から削除します。
クエリは次のとおりです。
SELECT ALERT_P, CNT, COLOUR, DFROMUIDCNT, FROMUIDCNT, IS_PRIORITYWORD, IS_STOPWORD, N, NIJ, NRTCNT, PJ, RTCCNT, RTCNT, TIME_STAMP, STEM, TWEETS FROM ALL_ALERTS WHERE (TIME_STAMP BETWEEN ? AND ?) ORDER BY TIME_STAMP, STEM
ああ、それは上記と同じなので、明らかにこれは Oracle に送信されているものではありません。
所要時間: 2.5 分。
したがって、EclipseLink プロパティは役に立ちますが、それを実現できれば、「Oracle11」の値の方が適切に機能する可能性があります。
構成 4
を削除したことを除いて、構成 3と同じORDER BY TIMESTAMP, STEM
です。
所要時間: 1.5 分。
構成 5
を削除したことを除いて、構成 1と同じORDER BY TIMESTAMP, STEM
です。
かかった時間: 25 秒。
構成 6
を復元し、からにORDER BY
移動しました。ojdbc6.jar
lib/ext
lib/
かかった時間: 26 秒。
構成 7
Config 6と同じですが、 を に変更しましたeclipselink.target-database
。Oracle11
今回のエラーは次のとおりです。
org.glassfish.deployment.common.DeploymentException: java.lang.NoClassDefFoundError: oracle/sql/TIMESTAMP
ext
Oracle固有の拡張機能を取得するには、jarが必要であることをwikiページが正しいことを確認します。
問題は、Oracle に送信されるクエリが最適化されていないことです。
誰でも教えてもらえますか:
- 「Oracle11」を使用するときの例外は何ですか(jarが入っているとき
ext/
)? - クエリを Oracle 用に最適化する他の方法はありますか?
次に@NamedNativeQuery
、SQLDeveloper で使用されているのと同じクエリを使用できるかどうかを確認します。クエリは複雑ではないので、これが JPA の機能を向上させるとは思えません。そのクエリは次のとおりです。
select * from all_alerts t1 WHERE t1.time_stamp between to_date('2013-01-22 16:00:00','YYYY-MM-DD HH24:MI:SS') and to_date('2013-01-22 16:05:00','YYYY-MM-DD HH24:MI:SS') ORDER BY t1.time_stamp, t1.stem;
実際に最初に試みることは、JPQL クエリで送信する日付が同じ形式であることを確認することです。
コメントやフィードバックをお待ちしております。
アップデート
さて、前に追加するのを忘れていた興味深いものがあります。以下@NamedQuery
は、予想される時間 (1 つのクエリで 0.086 秒) で実行されます。
@NamedQuery(name = "AllAlert.findLatestAlerts", query = "SELECT a FROM AllAlert a WHERE a.id.timeStamp in"
+ " (SELECT MAX(a.id.timeStamp) from AllAlert AS a) ORDER BY a.id.stem"),
これは私にはもっと複雑に思えます。