使用EntityManager(JPA)的DAO中update()方法的推荐行为?

时间:2014-10-13 16:11:13

标签: spring hibernate jpa dao entitymanager

我有一个REST服务,使用基本的CRUD方法来创建/读取/更新/删除我的资源。

我的DAO更新实现如下所示:

@Override
public Entity update(Entity entity) {
    final Entity updatedEntity = em.merge(entity);
    em.flush();
    return updatedEntity;
}

现在我不想更新"数据库中不可用的资源。为了解决这个问题,我编写了一个服务,该服务首先使用提供的id执行对资源的get调用。如果资源不可用,则会抛出无法更新资源的异常...

但这意味着每次REST更新调用都会有2个数据库调用。是否有一种推荐的方法来编写一个dao update()方法,如果该条目已经存在则抛出异常?当为未使用的资源执行PUT时,是否接受创建新条目?

1 个答案:

答案 0 :(得分:4)

merge()方法持久化尚未持久化的实体(没有ID或版本),并在实体持久时更新实体。因此,除了调用merge()(并将此调用返回的值返回到merge())之外,您不需要执行任何操作。

这意味着,如果实体没有ID,则会在DB上保留新记录。

    /**
     * Merge the state of the given entity into the
     * current persistence context.
     * @param entity  entity instance
     * @return the managed instance that the state was merged to
     * @throws IllegalArgumentException if instance is not an
     *         entity or is a removed entity
     * @throws TransactionRequiredException if invoked on a
     *         container-managed entity manager of type
     *         <code>PersistenceContextType.TRANSACTION</code> and there is
     *         no transaction
     */
    public <T> T merge(T entity);
  

3.2.4.1合并分离的实体状态

     

合并操作允许   从分离的国家传播   实体到持久化实体   由EntityManager管理。

     

合并操作的语义   应用于实体X如下:

     
      
  • 如果X是分离的实体,则X的状态将复制到预先存在的实体上   管理实体实例X'相同   X的身份或新的托管副本X'   已创建。
  •   
  • 如果X是新的实体实例,则创建新的管理实体实例X'   并将X的状态复制到   新的托管实体实例X'。
  •   
  • 如果X是已移除的实体实例,则IllegalArgumentException将是。{   由合并操作抛出(或者   事务提交将失败)。
  •   
  • 如果X是托管实体,则合并操作会忽略它,   但是,合并操作是   级联到由...引用的实体   X的关系,如果这些   关系已被注释   级联元素值   cascade=MERGEcascade=ALL   注释
  •   
  • 对于来自X的关系引用的所有实体Y具有   级联元素值cascade=MERGE或   cascade=ALL,Y以递归方式合并   作为Y'。对于所有这样的Y引用   X,X'设置为引用Y'。 (注意   如果X被管理,那么X就是   与X'相同的对象。)
  •   
  • 如果X是合并到X'的实体,则引用另一个实体Y,其中   cascade=MERGEcascade=ALL是。{   未指定,然后导航   来自X'的相同关联产生a   引用托管对象Y'   与Y相同的持久性身份。
  •   
     

持久性提供程序不能   合并标记为LAZY的字段没有   被抓取:它必须忽略这样   合并时的字段。

     

使用的任何Version列   必须通过实体检查实体   持久性运行时实现   在合并操作期间和/或在   刷新或提交时间。离席期间   Version列中没有   其他版本检查由   持久性提供程序运行时   合并期间。

1#更新策略

public Entity update(Entity entity) {
    final Entity find = em.find(...);
    if(find == null){
        throw new Exception();
    }
    //set ID into entity
    updatedEntity = em.merge(entity);
    return updatedEntity;
}

2#更新策略

@Transactional
public Entity update(Entity entity) {
    final Entity find = em.find(...);
    if(find == null){
        throw new Exception();
    }
    //set into find each value that you want update
    //when the transaction is closed, it will be updated the entity
    return find;
}

尽量避免使用em.flush()..这不是最佳做法。