我有一个带有JPA@Entity
注释的类,因此该类的对象在数据库中持久化并使用Hibernate ORM进行管理。在我的类构造函数中,创建了一个到MQTT代理的连接,因此初始化期间的每个对象都建立一个TCP连接。
当从数据库中获取对象数据时,ORM不能使用此构造函数,因为ORM使用默认构造函数而不带参数,因此我将建立连接的代码放在@PostLoad
注释方法中。
问题是,每次刷新web应用程序页面时,ORM都会被要求获取对象,并且执行@Postload
方法,因此TCP连接再次建立…但是我想要建立连接,只有第一次对象是从数据库中取出,而不是每次页面刷新。
所以解决方案是使用内存对象缓存的ORM。这样,第一次从数据库加载对象时,调用@Postload
方法,但下一次ORM被要求检索从缓存中检索的对象。
我不知道这是否可能与Hibernate,我一直在玩缓存选项和@Cacheable
注释,但似乎@Postload
方法被称为每次我使用存储库类的findById
方法,无论我设置的缓存选项。所以我猜Hibernate缓存是缓存表行,没有对象在内存中。
您可以使用具有扩展持久性上下文的实体管理器,该上下文跨越多个事务,但我不知道Spring Data如何或是否支持这一点。这样,实体就不会从数据库中重新加载,而是成为这个扩展持久化上下文的一部分。但请注意,这也会带来其他问题。
通常,这种昂贵的操作不会在实体中进行。您可以将逻辑移出类,或者执行某种连接池/缓存以避免重新连接。我不知道您为什么需要专用连接,但是连接到消息代理的方式通常不同。通常,这样的连接由库的某个上下文对象池化,或者Spring提供了一些与池化选项的集成。在Java/Jakarta EE中,这通常是通过资源适配器完成的。我敢打赌,您可以使用MQTT的JMS实现,可能也可以使用Spring。在Spring Data JPA中,您通常触发一个域/应用程序事件,然后在其他地方对该事件作出反应。在该侦听器中,您可以通过JMS或本机MQTT库将消息发布到主题/队列。