【问题标题】:JPA 2.1 right way (using eclipseLink) of updating an entity of my database?JPA 2.1 更新我的数据库实体的正确方法(使用 eclipseLink)?
【发布时间】:2014-09-05 12:37:10
【问题描述】:

我想知道我正在做什么来读取和更新我的数据库,它的方法和它的好习惯。

当我运行我的程序时,我将我的数据库加载到内存中:

 public static void open() {
  EntityManagerFactory emf = Persistence.createEntityManagerFactory("htTeamManagerPU");
  EntityManager em = emf.createEntityManager();
  TypedQuery<Season> query = em.createQuery("select s from Season s",Season.class);
  seasons = query.getResultList(); }

通过这样做,我在我的数据库中保存了特定赛季的球员。

现在我有了我的 playerList,它是一个玩家列表,我想在内存中更新它,然后在我的数据库中更新该玩家。我可以做不同的事情,因为我已经在内存中拥有播放器,我仍然需要找到播放器并进行与之前在内存中所做的相同的更改?看来我做了两次同样的改变......

public void finishTraining(int id){
  EntityManagerFactory emf = Persistence.createEntityManagerFactory("htTeamManagerPU");
  EntityManager em = emf.createEntityManager();
  em.getTransaction().begin();
   for (Player player: playerList){
       if (player.getPlayerId()==id) {
           player.setIsTeam((short)0);
           player.setIsToSell((short)1);
           //no i find the player in my database with id primary key
           Player p1 = em.find(Player.class, id);
           //make the same changes i already did in memory
           p1.setIsTeam((short)0);
           p1.setIsToSell((short)1);
           //submit my changes? there is another way of doing this?
           em.getTransaction().commit();

       }
   } 
   em.close();
   emf.close();
}

这工作正常并更新我的数据库。我想知道这是否是正确和最好的方法。谢谢

【问题讨论】:

标签: jpa eclipselink


【解决方案1】:

首先,您不会做两次相同的更改。

在 EntityManager 生命周期中(这是一种简化,因为有事务的超时概念和更多东西)它监视检索的实体发生的情况,因此,如果修改,它们的更改将被转换到数据库,但是一旦 EntityManager 生命周期结束,所有监控也结束。问题是您习惯于隐式操作(在您的代码中没有 EntityManager 的合并、删除或删除功能,因此它是自己的 EntityManager 关心如何处理更改)而不是显式(使用 EntityManager 的合并、删除或创建由程序员声明的方法),因此您可能认为一旦实体被修改,它就会自动提交,但不是:更改由 EntityManager 处理

由于 playerList 可能是在 EntityManager 生命周期之外修改的,没有人关心它的实体,因此数据库不会刷新更改,这会导致您的问题。

在我所描述的情况下,这种缺乏刷新是完全正常的。对于未处理的实体,获取实体管理器、开始事务等过程是完全正常的。

关于您的问题“我想知道这是否是正确和最好的方法”,我已经解释了这个概念,但我可以建议一些代码改进。 例如,我会避免隐式 EntityManager 操作以避免混淆;使用显式方法我会这样改变你的方法:

public void modifiedFinishTraining(int id){

/*This three lines are mandatory. You have to get an EntityManager to get access to     database and start a transaction to store your changes*/
EntityManagerFactory emf = Persistence.createEntityManagerFactory("htTeamManagerPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

/*case 1: use merge method. If you want to update your player or create if it is not at database, use it and avoid the em.find(Player.class, id) step*/
for (Player player: playerList){

if (player.getPlayerId()==id) {
//This way you avoid the step of find by be careful: merge updates existing or creates a new one.
em.merge(player);
}

}
/*case 2: If you want to check if exists and you dont want to create it in other case  do it*/
for (Player player: playerList){
  if (player.getPlayerId()==id) {
      //you find the player in database
       Player p1 = em.find(Player.class, player.getPlayerId());
       //check if player exists and if true, update           
       if(p1  != null){
         p1.setIsTeam((short)0);
         p1.setIsToSell((short)1);

         em.merge(p1);
       }
   }
}

//this would be done at the end of the operation to commit all changes at the same time
em.getTransaction().commit();   
em.close();
emf.close();
/*the upper three lines are mandatory. You must commit your changes because transaction is manually handled and once commited you have to close all to free resources*/

}   

【讨论】:

    猜你喜欢
    • 2012-03-31
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 2015-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多