Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用JPA手动控制数据库更新_Java_Jpa_Entitymanager - Fatal编程技术网

Java 使用JPA手动控制数据库更新

Java 使用JPA手动控制数据库更新,java,jpa,entitymanager,Java,Jpa,Entitymanager,我正在考虑在应用程序中使用JPA,以便持久化许多对象 不过,应用程序的使用似乎不符合标准JPA方法,即在对象的每次更改时进行更新 应用程序的使用将使得一次只有几百个对象处于活动状态,但这些对象将每秒更新几次 虽然应用程序在内存中有对象,但不需要在数据库中不断更新它们,这只是无用的IO 是否可以使用JPA在会话中加载一些对象,并且在不影响其他实体管理的对象的情况下,在内存中对它们进行几分钟的更改,然后更新数据库 如果有一种方法可以在会话之间共享某些对象,这将非常有用。如果您不想对实体进行DB更改,

我正在考虑在应用程序中使用JPA,以便持久化许多对象

不过,应用程序的使用似乎不符合标准JPA方法,即在对象的每次更改时进行更新

应用程序的使用将使得一次只有几百个对象处于活动状态,但这些对象将每秒更新几次

虽然应用程序在内存中有对象,但不需要在数据库中不断更新它们,这只是无用的IO

是否可以使用JPA在会话中加载一些对象,并且在不影响其他实体管理的对象的情况下,在内存中对它们进行几分钟的更改,然后更新数据库


如果有一种方法可以在会话之间共享某些对象,这将非常有用。

如果您不想对实体进行DB更改,只需将它们从实体管理器中分离出来即可

  • 要在事务期间从实体管理器分离对象,只需使用方法
  • 如果该实体未被管理(即在交易结束后),则该实体无论如何也未被管理,并且您可以对其进行任何更改,而无需额外代码
  • 摘自JPA 2.0规范,关于实体如何分离:

    如果 使用事务范围的容器管理实体管理器(请参阅 第3.3节);来自事务回滚(见第3.3.2节)来自 从持久性上下文中分离实体;从清除 持久性语境;关闭实体管理者;或来自 序列化实体或以其他方式通过值传递实体,例如,传递给 一个单独的应用层,通过远程接口等

    然后,当决定更改数据库时,只需合并分离的实体:
    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;
    

    我确实想更改数据库,我只是想控制它何时发生,以及对哪些对象进行更改。更新了我的答案。您只需在分离状态和托管状态之间移动实体即可。谢谢!最后一个小问题是:合并和分离的范围是什么?假设我有许多“根对象”,它们与一些其他对象有一对一或一对一的关系,可以在根对象之间共享。在根对象上调用“分离”和“合并”时会发生什么?我是只为根对象调用方法,还是为所有对象调用方法