在桌面SWING应用程序中使用JPA

5
我正在开发一个使用SWING的单用户桌面应用程序。我之前有一些此类应用程序的经验,当时我使用了java.sql API,但我意识到这并不舒适...

在我的新应用程序中,我正在尝试首次使用JPA,我阅读了很多教程,几乎都让我明白了我需要知道的所有内容,但没找到一个好的真实Java桌面应用程序的例子。

我想使用以下架构,但不确定是否正确...
我打算创建一个MyPersistenceUnit类:
    public class MyPersistenceUnit {
        private static EntityManagerFactory factory;
        private static EntityManager entityManager;

        public static void initiate(){
            factory=Persistence.createEntityManagerFactory("PU_Name");
            entityManager=factory.createEntityManager();
        }

        public static EntityManager getEntityManager() {
            return entityManager;
        }

        public static void close(){
            entityManager.close();
            factory.close();
        }

    }

在应用程序启动时,将首先调用initiate()方法,并在应用程序关闭时调用close()方法。

应用程序运行时,所有事务都将通过getEntityManager()实例完成,该实例可在应用程序中的任何位置访问。如果我正确理解JSE应用程序,则获取的实体管理器具有扩展持久性上下文,而实体管理器未关闭时将保持所有实体处于受管理状态,这就是我这样想的原因...

我不知道是否遗漏了什么,所以任何提示将不胜感激

请注意,我正在使用嵌入式数据库derby的eclipselink提供程序。
谢谢


我认为这个问题与Swing无关。 - Hovercraft Full Of Eels
抱歉,我已经删除了标签。 - George Casttrey
4个回答

5
据我所知,问题归结为您是否应该打开EntityManager并全局存储其引用,并在应用程序的任何地方访问相同的实例。
我认为如果您的应用程序规模较小到中等,那么这应该是可以的。只需注意数据库连接(因此是会话/实体管理器)可能由于各种因素而断开。不要在事务中执行此操作(例如,不要在开始时打开它们并在结束时提交)。尽可能细粒度地保持事务。
曾经有过各种讨论,更有经验的人讨论了这个问题,您可以在这里关注:forcounter关于这个SO问题的论点-使用Hibernate在Swing应用程序中进行会话管理 此外,还请参见this有关同一主题的内容。
这是一个由Hibernate的提交者创建的示例桌面应用程序,在这里。它有点老了,但你可以得到想法。
最后,这篇文章 是理解桌面应用程序的一般JPA概念的好文章。

我认为我会采用反方观点,因为我认为我的应用程序比中等规模稍微大一些。现在的问题是,我熟悉 EclipseLink,甚至我检查过的测试链接显示 EclipseLink 更好,不幸的是,所有解决问题的文章都在谈论 Hibernate。关于你给出的最后一个链接,它只展示了一些非常基本的例子,所以它并没有真正解决我的问题。 - George Casttrey
我很高兴你能根据那些链接做出选择。如果你问我的个人意见,我会建议不要长时间保持会话/EM开启状态,只有在需要时才打开它。关于Eclipselink,我自己从未在任何实际项目中使用过它,所以我无法对此发表评论,但我希望在概念上不会有太大的区别。 - kdabir
1
最终,我决定使用长生命周期的持久化上下文,但将'eclipselink.persistence-context.reference-mode'属性设置为'WEAK',这将负责任何内存管理问题。我还将<shared-cache-mode>元素设置为“NONE”,这将禁用第二级缓存,在我的情况下是无用的,并且仅使用L1缓存(与EM相关)。我认为这是最合理的解决方案,因为为每个事务创建一个新的EntityManager可能很昂贵。非常感谢@kunal的帮助。 - George Casttrey
1
@GeorgeCasttrey,很高兴我的回复有所帮助。感谢您发布解决方案,这肯定会帮助到未来搜索同一主题的人们。 - kdabir

3

重新思考了我的设计后,我决定做如下更改:

  • 在应用程序启动时创建一个“永久”的EM,并保持其开放直到应用程序关闭。permanentEM将用于在需要时查找/刷新实体(例如获取延迟关系...)。为确保WEAK引用模式有效地管理内存,我将避免永久引用permanentEM的托管实体。
  • 创建一个“临时”的EM来加载应用程序启动所需的“永久”数据。一旦数据加载完毕,关闭该临时EM以分离所有已加载到内存中的数据。
  • 为每个persist/merge/remove事务创建一个新的“临时”EM,并在事务提交后关闭它。

2
注意:我在一个生产系统上使用Eclipselink已经有一年时间,该系统的设计非常相似。虽然这个应用程序实际上是一个EE框架,但我不得不在各种应用服务器之间跳来跳去,并且自己管理事务。Eclipselink在超时、缓存和“正常工作”方面做得非常好。如果您与数据有客户端-服务器关系,则您所建议的内容将很好地发挥作用(缓存可能无法反映DB的状态)。如果您没有使用缓存,则可能会看到一些性能提升。祝你好运。 - Daniel B. Chapman

0

0

由于这是一个SE应用程序,您可以使用嵌入式数据库。

我知道H2通常只允许一个线程访问,因此如果您在相同的开发环境中并且想要避免实体的头痛并发控制,我的建议是将您的服务调用封装在一个线程中,并为该线程分配一个entitymanager。

不要允许其他线程使用实体,然后定义数据访问接口,可以将数据从实体传输到其他对象中的适当数据结构中。

总之,我认为最好将所有实体放在一个entity manager域中,并将它们与其他线程隔离开来。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接