1

我正在开发一个由 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 正在发送到数据库的查询:

<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.jarfrom移动lib/extlib/

耗时:26 秒。

配置 7

配置 6相同,但更改eclipselink.target-databaseOracle11,这次错误是:

org.glassfish.deployment.common.DeploymentException: java.lang.NoClassDefFoundError: oracle/sql/TIMESTAMP

验证 wiki 页面是否正确,jar 需要在ext其中获取特定于 Oracle 的扩展。

在我看来,问题在于发送到 Oracle 的查询没有针对它进行优化。

谁能告诉我:

  1. 使用“Oracle11”时的异常是什么(当罐子在时ext/)?
  2. 有没有其他方法可以针对 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在预期时间内运行(一次查询为 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"),

这对我来说似乎更复杂。

4

0 回答 0