【问题标题】:Updating an object using JPA / an entityManager使用 JPA / entityManager 更新对象
【发布时间】:2017-01-19 14:03:02
【问题描述】:

我有一个在 Wildfly 10 上运行的 Java/Spring Web 应用程序。我配置了 JPA,想知道执行更新和删除语句的常用方法是什么。例如,一个 httprequest 进入服务器以显示有关 Person 记录的所有详细信息。我将使用实体管理器查找此记录

class PersonDao
{
    @PersistenceContent
    entityManager entityManager

    public Person findPerson(int id)
    {
         assert(id >= 0); //pseudocode

         Person p = this.entityManager.find(Person.class,id);

         assert(p != null); //pseudocode

         return p;
    }
}

然后这个人的详细信息显示在屏幕上,请求完成,线程消失。在我的代码中不再可以访问实体管理器中附加的人员记录。

一段时间后,用户发起了一个新请求以更新此人的年龄。目前在我的 Dao 课程中,我总是重新找到记录,所以我确信它存在于我的持久性上下文中,但它似乎是多余和乏味的。我想知道一个更好的方法来实现这个:

    public void updatePersonAge(int id, int newAge)
    {
         assert(newAge >= 0)

         Person p = this.findPerson(id);

         p.setAge(newAge);

         this.entityManager.persist(p);
    }

【问题讨论】:

  • persist 不适用于更新。使用的调用是merge(),甚至可能是多余的,JPA 会跟踪托管实体上的更改,并自动将这些更改与数据库同步。

标签: java jpa entitymanager hibernate-entitymanager


【解决方案1】:

我这样做的方法是创建一个 PersonRepository 而不是 PersonDao。 "Spring Data JPA for more info."

一旦你知道它就很容易学习并且很棒。你的 Dao 现在只是一个接口,基于它的查询看起来像......

public interface PersonRepository extends JpaRepository<Person, Integer> { 
    //custom queries here...
}

即使您在此文件中没有放置任何内容,您现在也可以从 JpaRepository 中创建、更新、查找和删除所有内容。

然后我会创建一个 PersonService 来处理上述情况

@Service
public class PersonService {

    private PersonRepository personRepository        

    @Autowired
    public PersonService(PersonRepository personRepository) {
        this.personRepository = personRepository;
    }

    // typically you would have create, findById and other methods here

    public void updatePersonAge(int id, int newAge) {
        assert(newAge >= 0)

        Person p = personRepository.findOne(id);

        p.setAge(newAge);

        personRepository.save(p);
   }

   // but if you want an easy way to do this and you can 
   // serialize the whole object instead of just get the id you can
   // simply call and update method
   public Person update(Person person) {
       assert(person.getId() != null);
       return personRepository.save(person);
   }

}

这是假设您可以使用对象中已有的新年龄直接序列化对象

这可能不是您正在寻找的解决方案,因为我没有直接使用实体管理器

【讨论】:

  • 我非常感谢这个输入,但是在阅读了教程之后,我觉得这对我来说太过分了。我只是学习/使用 JPA 的新手,所以现在添加另一层抽象/框架还为时过早。这是我在 JPA 中感到舒服(或对样板文件感到厌烦)后会再次查找的东西。谢谢!
  • 如果您需要示例,请告诉我!看起来很多,但实际上比您想象的要容易,学习不同的层也不是太难,我通常使用存储库(Dao)、服务(业务逻辑)和控制器(其余端点)模式。似乎有很多抽象,但分离关注点很好。我还使用 Hibernate/JPA 将实体直接转换为 DB 表。但是,如果您仍然只是为个人项目学习和探索 JPA,您可以忽略我所说的。很容易被不熟悉的主题弄得不知所措,无需添加不必要的混乱。
【解决方案2】:

你这样做的方式是正确的,调用

Person p = this.findPerson(id);

要(再次)获取正确的 Person 对象,需要对其进行更新,因为正如您所描述的,实体管理器无法再访问 Person 对象。

【讨论】:

  • 关于性能,实体管理器实际上是在做另一个选择,还是从缓存中检索人员对象?
  • 在这种情况下它使用另一个选择。
猜你喜欢
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 2012-09-08
  • 2014-12-08
  • 2015-03-08
相关资源
最近更新 更多