@Override
  public List<ID> upsert(Iterable<T> dEntities) {
    final TransactionStatus transactionStatus = getTransaction();

    // group entities by create or update:
    final ArrayList<T> toCreate = new ArrayList<T>();
    final ArrayList<T> toUpdate = new ArrayList<T>();
    ID id;
    for (T d : dEntities) {
      id = dao.getSimpleKey(d);
      if (null == id) {
        toCreate.add(d);
      } else {
        toUpdate.add(d);
      }
    }
    LOG.debug("Creating {}, Updating {}", toCreate.size(), toUpdate.size());
    LOG.debug("Creating {}, Updating {}", toCreate, toUpdate);

    try {
      // create new entities using async API
      Future<List<?>> createFuture = null;
      if (!toCreate.isEmpty()) {
        createFuture = dao.persistForFuture(toCreate);
      }

      // update in parallel
      if (!toUpdate.isEmpty()) {
        dao.update(toUpdate);
      }

      // join future
      if (null != createFuture) {
        Collection<ID> ids = dao.getSimpleKeys(createFuture);
        //            Iterator<ID> i = ids.iterator();
        //            for (T t : toCreate) {
        //                dao.setSimpleKey(t, i.next());
        //            }
      }

      // collect the IDs
      final ArrayList<ID> body = new ArrayList<ID>();
      for (T d : dEntities) {
        body.add(getSimpleKey(d));
      }

      commitTransaction(transactionStatus);
      return body;
    } finally {
      rollbackTransaction(transactionStatus);
    }
  }
  @Override
  public ID update(T domain) {
    final TransactionStatus transactionStatus = getTransaction();
    preDao();
    try {
      LOG.debug("Update {}", domain);
      final ID id = dao.getSimpleKey(domain);
      if (null == domain || null == id) {
        throw new IllegalArgumentException("ID cannot be null updating " + dao.getTableName());
      }

      dao.update(domain);

      commitTransaction(transactionStatus);
      return id;
    } finally {
      postDao();
      rollbackTransaction(transactionStatus);
    }
  }
 @Override
 public ID getSimpleKey(T domain) {
   return dao.getSimpleKey(domain);
 }