Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.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
处理JPA合并的最佳方法?_Jpa_Jta - Fatal编程技术网

处理JPA合并的最佳方法?

处理JPA合并的最佳方法?,jpa,jta,Jpa,Jta,我对整个JPA都是新手,所以我对处理JPA合并和持久化的最佳方法有很多疑问 我有一个应该更新的用户对象(一些值,如日期和名称)。我必须先合并传递的对象,还是更安全地找到新对象 当前,我用于更新用户的代码如下所示: public void updateUserName(User user, String name) { // maybe first merge it? user.setName(name); user.setChangeDate(new Date())

我对整个JPA都是新手,所以我对处理JPA合并和持久化的最佳方法有很多疑问

  • 我有一个应该更新的用户对象(一些值,如日期和名称)。我必须先合并传递的对象,还是更安全地找到新对象

    当前,我用于更新用户的代码如下所示:

    public void updateUserName(User user, String name) {
         // maybe first merge it?
         user.setName(name);
         user.setChangeDate(new Date());
         em.merge(user);   
     }
    
    在调用update方法之前,如何确保用户没有被操纵?这样做是否更安全:

     public void updateUserName(int userId, String name) {
         User user = em.getReference(User.class, userId);
         user.setName(name);
         user.setChangeDate(new Date());
         em.merge(user);   
     }
    
    也许还有其他解决办法?我看了多个视频,看到了很多例子,但它们都不同,没有人解释什么是最佳实践

  • 将孩子添加到人际关系中的最佳方法是什么?例如,我的用户对象连接到多个组。我应该为用户调用JPA处理程序并将新组添加到用户组列表中,还是应该使用persist在so组处理程序中创建组并手动将其添加到我的用户对象中


  • 希望这里有人有线索;)

    问题1

    • 必须对分离的实体调用
      merge
      方法
    • merge
      方法将合并的对象返回给entityManager
    这是什么意思

    一个实体在您用来获取它的entityManager关闭后就被分离。(即,大部分时间是因为您在以前的交易中获取了它)

    在您的第二个代码示例中:user被附加(因为您只是获取它),所以调用merge是无用的。(顺便说一句:它不是
    getReference
    ,而是
    find

    在您的第一个示例中:我们不知道用户的状态(是否分离实体?)。如果它被分离,调用
    merge
    是有意义的,但是要小心
    merge
    不要修改作为参数传递的对象。以下是我对您的第一个示例的版本:

    /**
     * @param user : a detached entity
     * @return : the attached updated entity
    **/
    public User updateUserName(User user, String name) {
       user.setName(name);
       user.setChangeDate(new Date());
       return em.merge(user);   
    }
    
    问题2

    也许一些解释jpa处理程序含义的代码示例可以帮助我们理解您的担忧。不管怎样,我会尽力帮助你的

    如果您有一个持久用户,并且需要创建一个新组并将其与持久用户关联:

    User user = em.find(User.class, userId);
    Group group = new Group();
    ...
    em.persist(group);
    user.addToGroups(group);
    group.addToUsers(user); //JPA won't update the other side of the relationship
                            //so you have to do it by hand OR being aware of that 
    
    如果您有一个持久用户和一个持久组,并且需要将它们关联起来:

    User user = em.find(User.class, userId);
    Group group = em.find(Group.class, groupId);
    ...
    user.addToGroups(group);
    group.addToUsers(user);
    
    一般注意事项

    关于所有这些的最佳实践实际上取决于您管理事务(以及entityManager的生命周期)和对象的生命周期

    大多数情况下:entityManager是一个非常短的生命体。另一方面,您的业务对象可能会存在更长的时间,因此您必须调用merge(注意merge不会修改传入参数的对象!!!)

    您可以决定在同一事务中获取和修改业务对象(即使用同一entityManager):这意味着需要更多的数据库访问,出于性能原因,此策略通常必须与二级缓存相结合。但在这种情况下,您不必调用merge

    我希望这有帮助

  • 这取决于您想要实现什么,以及您有多少关于要合并的对象的原点的信息

    首先,如果您在方法的第一行或最后调用
    em.merge(user)
    ,这并不重要。如果您使用JTA和CMT,当方法调用完成时,您的实体将被更新。唯一的区别是,如果在更改用户之前调用
    em.merge(user)
    ,则应使用返回的实例而不是参数,因此:

    public void updateUserName(User user, String name) {
       User managedUser = em.merge(user);
       managedUser.setChangeDate(new Date());
       // no need of additional em.merge(-) here.
       // JTA automatically commits the transaction for this business method.
    }
    

    现在关于更新实体。
    如果您只想更新实体中一些定义良好的字段,请使用第二种方法,因为它更安全。您无法确定您的方法的客户端是否未修改实体的某些其他字段。因此,
    em.merge(-)
    也将更新它们,这可能不是您想要实现的

    另一方面,如果您希望接受用户所做的所有更改,并在示例中覆盖/添加一些属性,如
    changeDate
    ,那么第一种方法也很好(合并传递给业务方法的整个实体)。这实际上取决于您的用例

  • 我想这取决于你的级联设置。如果您想在
    用户
    实体更改时自动持久化/合并所有
    ,只需将其添加到用户集合(类似于
    User#addGroup(Group g){Groups.add(g)}
    。如果您不希望级联,您可以始终创建自己的方法,这些方法将传播到关系的另一端。它可能类似于:
    User#addGroup(Group g)
    自动调用
    g.addUser(this);


  • 谢谢你的回答。关于我的问题1,在调用JPA处理程序的方法中设置date和new name之类的字段,然后调用方法“updateUser(用户用户)”来合并用户对象并保存所有更改,而不是为几个更新用例创建方法,这不是最简单的方法吗?请参阅
    public void updateUserName(User user, String name) {
       user.setChangeDate(new Date());
       em.merge(user);
       // JTA automatically commits the transaction for this business method.
    }