java Hibernate加快EntityManagerFactory创建
在我的桌面应用程序中,新数据库经常被打开。我使用Hibernate
/JPA
作为ORM。
问题是,创建EntityManagerFactory
的速度非常慢,在高速机器上大约需要5-6秒。我知道EntityManagerFactory
应该是重量级的,但对于用户希望快速打开新数据库的桌面应用程序来说,这太慢了
我可以关闭一些EntityManagerFactory功能来获取实例吗 更快?或者有没有可能懒散地创建一些EntityManagerFactory来加速cration
我可以在之前创建EntityManagerFactory对象吗 知道数据库url吗?我很乐意关掉所有的 对此进行验证是可能的
这样,我可以将整个ManagerFactory集中起来供以后使用吗
还有其他更快创建EntityManagerFactory的方法吗
更新更多信息和JProfiler评测
桌面应用程序可以打开保存的文件。我们的应用程序文档文件格式由1个SQLite database+和一个ZIP文件中的一些二进制数据组成。打开文档时,会提取ZIP文件,并使用Hibernate打开数据库。这些数据库都有相同的模式,但数据明显不同
似乎我第一次打开一个文件所花的时间比接下来的时间要长得多。 我用JProfiler分析了第一次和第二次运行,并比较了结果
第一轮:
create EMF: 4385ms
build EMF: 3090ms
EJB3Configuration configure: 900ms
EJB3Configuration <clinit>: 380ms
第二轮:
create EMF: 1275ms
build EMF: 970ms
EJB3Configuration configure: 305ms
EJB3Configuration <clinit>: not visible, probably 0ms
在调用树比较中,您可以看到一些方法明显更快(DatabaseManager.作为起点):
create EMF: -3120ms
Hibernate create EMF: -3110ms
EJB3Configuration configure: -595ms
EJB3Configuration <clinit>: -380ms
build EMF: -2120ms
buildSessionFactory: -1945ms
secondPassCompile: -425ms
buildSettings: -346ms
SessionFactoryImpl.<init>: -1040ms
热点比较现在有了有趣的结果:
ClassLoader.loadClass: -1686ms
XMLSchemaFactory.newSchema: -184ms
ClassFile.<init>: -109ms
我不确定是加载Hibernate类还是实体类
第一个改进是在应用程序启动后立即创建EMF,只是为了初始化所有必要的类(我的应用程序已经附带了一个空的db文件作为原型)@sharakan感谢您的回答,也许延迟连接提供商已经是这个问题的解决方案
下一步我将尝试延迟连接提供商!但我们或许可以进一步加快速度。你还有什么建议吗
# 1 楼答案
你应该能够通过实现你自己的
ConnectionProvider
作为一个真正的ConnectionProvider
的装饰器来做到这一点这里的关键观察结果是
ConnectionProvider
在创建EntityManager
之前不会被使用(请参见supportsAggressiveRelease()
中的注释以获取警告)。因此,您可以创建一个DeferredConnectionProvider
类,并使用它来构造EntityManagerFactory
,但随后等待用户输入,并在实际创建任何EntityManager
实例之前进行延迟初始化。我是作为ConnectionPoolImpl
的包装器编写的,但是您应该能够使用ConnectionProvider
的任何其他实现作为基础关于如何使用它的一个粗略示例:
您可以将
EntityManagerFactory
的初始设置放在一个单独的线程或其他东西上,这样用户就不必等待它了。那么,在指定连接信息之后,他们唯一需要等待的就是连接池的设置,与解析对象模型相比,这应该是相当快的# 2 楼答案
别这么认为。除了初始化JDBC连接/池,EMF实际上没有太多功能
当用户注意到性能受到影响时,我建议您不要懒洋洋地创建EMF,而应该朝相反的方向前进——在用户真正需要之前主动创建EMF。在应用程序初始化期间(或者至少在您了解数据库后)在单独的线程中提前创建一次。在应用程序/数据库的整个存在过程中重用它
否-它会创建一个JDBC连接
我认为更好的问题是:为什么应用程序动态地发现数据库连接URL?你是说你的数据库是动态创建的/可用的,没有办法提前预测连接参数。这确实是应该避免的
不,你不能共用EMF。这是你可以共享的连接
我同意-6秒对于EMF的初始化来说太慢了
我怀疑这更多地与您选择的数据库技术有关,而不是JPA/JDBC/JVM。我的猜测是,可能你的数据库正在初始化自己,因为你连接。你在使用Access吗?你用的是什么数据库
你正在连接远程数据库吗?为了一个万?网络速度/延迟是否良好
客户端PC的性能是否受到限制
编辑:在评论后添加
在真正的ConnectionProvider周围实现自己的ConnectionProvider作为装饰器,根本不会加快用户的体验。数据库实例仍然需要初始化,EMF&;EM已创建,JDBC连接仍需随后建立
选项:
(2)可能会在有限的努力下实现最好的改进
此外: -尝试在部署期间而不是在应用程序使用期间解压缩数据文件。 -在与UI启动并行运行的启动线程中初始化EMF——尝试启动DB初始化,作为应用程序的第一步之一(这意味着使用JDBC连接到实际实例)