private boolean updateStrict(T model, UpdateStatementPreparer<T> usp, Long oldUpdatedAt) throws TooManyRowsUpdatedException, StaleModelException, IOException {
    try {
      final PreparedStatement saveStmt = conn.getPreparedStatement(usp.getSaveStmt());
      usp.setParams(this, model, saveStmt);
      saveStmt.execute();
      final int updateCount = saveStmt.getUpdateCount();
      saveStmt.close();

      // since the statement includes id we expect at most 1 row to be updated
      if (updateCount > 1) {
        throw new TooManyRowsUpdatedException();
      } else if (updateCount < 1) { // no row updated => id or lock_version is non-matching => stale
        // don't match Rails behaviour (updated_at changed on field modification)
        // do    match Jack  behaviour (updated_at changed on successful save)
        revertRailsUpdatedAt(model, oldUpdatedAt);
        throw new StaleModelException();
      } else {

        // Locking will not prevent clobbering if the cache is used to fetch the
        // two models since they are the same reference, and hence modifying one
        // is modifying the other.
        // We still want the right result in there, though.
        if (useCache) {
          cachedById.put(model.getId(), model);
        }
        clearForeignKeyCache();

        return true;
      }

    } catch (SQLException e) {
      revertRailsUpdatedAt(model, oldUpdatedAt);
      throw new IOException(e);
    }
  }