Java 使用JPA手动控制数据库更新
我正在考虑在应用程序中使用JPA,以便持久化许多对象 不过,应用程序的使用似乎不符合标准JPA方法,即在对象的每次更改时进行更新 应用程序的使用将使得一次只有几百个对象处于活动状态,但这些对象将每秒更新几次 虽然应用程序在内存中有对象,但不需要在数据库中不断更新它们,这只是无用的IO 是否可以使用JPA在会话中加载一些对象,并且在不影响其他实体管理的对象的情况下,在内存中对它们进行几分钟的更改,然后更新数据库Java 使用JPA手动控制数据库更新,java,jpa,entitymanager,Java,Jpa,Entitymanager,我正在考虑在应用程序中使用JPA,以便持久化许多对象 不过,应用程序的使用似乎不符合标准JPA方法,即在对象的每次更改时进行更新 应用程序的使用将使得一次只有几百个对象处于活动状态,但这些对象将每秒更新几次 虽然应用程序在内存中有对象,但不需要在数据库中不断更新它们,这只是无用的IO 是否可以使用JPA在会话中加载一些对象,并且在不影响其他实体管理的对象的情况下,在内存中对它们进行几分钟的更改,然后更新数据库 如果有一种方法可以在会话之间共享某些对象,这将非常有用。如果您不想对实体进行DB更改,
如果有一种方法可以在会话之间共享某些对象,这将非常有用。如果您不想对实体进行DB更改,只需将它们从实体管理器中分离出来即可
entityManager.merge(entity)代码>
我认为,您缺少一些JPA背景,例如实体的状态和entityManager的操作。我建议您搜索一些教程,或者阅读(阅读第3.2章实体实例的生命周期)中的一些章节
,大约5页,我保证你会理解很多)。此外,如果您希望合并操作级联,JPA中也有一个解决方案。
对于EntityManager上的操作&JPA中的良好介绍:
更新
我将试着简短地向您描述在这些教程中找到什么是重要的
如果实体实例(即持久性java对象)与持久性上下文(~ EntityManager)关联,则该实体实例将被管理。如果它是托管的,那么它的更改将被跟踪,这意味着对托管实体实例的更改将同步到DB。更改将同步到数据库,例如,当事务完成时,或当您调用entityManager.flush()
(有关更多详细信息,请阅读第3.2.4节“与数据库同步”)
合并操作实际上是更新和持久化实体实例的操作。它返回一个托管实体实例E2,而传递的实体E1保持未托管状态
另一侧分离的实体不会被entityManager
跟踪,这意味着entityManager不会看到您所做的更改,除非您不合并该实体
这两个操作(还有一个persist操作,我没有讨论)都是切换managedAttached实体实例状态的方法
现在与您关于root和children的问题相关:如果未配置任何内容,则在root上调用merge()
或detach()
,将不会影响您的孩子。但是有一个级联方案可以在JPA中使用,因此,例如调用entityManager.merge(root)
,也将在其子级上调用。当然,您可以决定哪些操作级联,哪些不级联。您可以通过创建自己的实体管理器来控制实体的预期寿命
不清楚您是在谈论JEE还是独立应用程序,但在任何情况下,您都需要获得对entity manager工厂的访问权,并从中获得一个entity manager
您的实体管理器将链接到持久性上下文。每次您请求一个实体时,它都会被放置在这个持久性上下文中。如果保持实体管理器处于打开状态,则只有在第一次读取实体时才会访问数据库。下一次,您将从这个缓存中获取它们
如果使用资源本地事务,则可以控制将更改刷新到数据库的时间。因此,您可以在一定时间内更改上下文,然后通过提交事务或调用flush方法来决定刷新它
您可能希望阅读本文,以进一步了解持久性上下文及其工作方式
--编辑--
根据您正在构建的应用程序的类型,有多种方法可以访问entity manager工厂
如果这是一个独立的应用程序,您可以
EntityManagerFactory emf = Persistence.createEntityManagerFactory("unit-name");
如果您使用的是依赖项注入框架,那么可以使用它自动注入依赖项。如果您在JEE应用程序中,您可以使用
@PersistenceUnit(unitName="main")
private EntityManagerFactory emf;
我确实想更改数据库,我只是想控制它何时发生,以及对哪些对象进行更改。更新了我的答案。您只需在分离状态和托管状态之间移动实体即可。谢谢!最后一个小问题是:合并和分离的范围是什么?假设我有许多“根对象”,它们与一些其他对象有一对一或一对一的关系,可以在根对象之间共享。在根对象上调用“分离”和“合并”时会发生什么?我是只为根对象调用方法,还是为所有对象调用方法