// TODO move that code to the EntityLoader as it is in AbstractEntityPersister?
  @Override
  public Object loadByUniqueKey(String propertyName, Object uniqueKey, SessionImplementor session)
      throws HibernateException {
    // we get the property type for an associated entity
    final int propertyIndex = getPropertyIndex(propertyName);
    final GridType gridUniqueKeyType =
        getUniqueKeyTypeFromAssociatedEntity(propertyIndex, propertyName);
    // get the associated property index (to get its column names)
    // find the ids per unique property name
    AssociationKeyMetadata associationKeyMetadata =
        associationKeyMetadataPerPropertyName.get(propertyName);
    if (associationKeyMetadata == null) {
      throw new AssertionFailure("loadByUniqueKey on a non EntityType:" + propertyName);
    }
    AssociationPersister associationPersister =
        new AssociationPersister(getMappedClass())
            .gridDialect(gridDialect)
            .key(uniqueKey)
            .keyGridType(gridUniqueKeyType)
            // does not set .collectionPersister as it does not make sense here for an entity
            .associationKeyMetadata(associationKeyMetadata)
            .session(session)
            .propertyType(getPropertyTypes()[propertyIndex]);
    final Association ids = associationPersister.getAssociationOrNull();

    if (ids == null || ids.size() == 0) {
      return null;
    } else if (ids.size() == 1) {
      // EntityLoader#loadByUniqueKey uses a null object and LockMode.NONE
      // there is only one element in the list, so get the first
      Tuple tuple = ids.get(ids.getKeys().iterator().next());
      final Serializable id =
          (Serializable)
              getGridIdentifierType().nullSafeGet(tuple, getIdentifierColumnNames(), session, null);
      return load(id, null, LockMode.NONE, session);
    } else {
      throw new AssertionFailure(
          "Loading by unique key but finding several matches: table:"
              + getTableName()
              + " property: "
              + propertyName
              + " value: "
              + uniqueKey);
    }
  }
  private List<Map<String, Object>> getAssociationRows(
      Association association, AssociationKey associationKey) {
    List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();

    for (RowKey rowKey : association.getKeys()) {
      Tuple tuple = association.get(rowKey);

      Map<String, Object> row = new HashMap<String, Object>(3);
      for (String columnName : tuple.getColumnNames()) {
        // don't store columns which are part of the association key and can be retrieved from there
        if (!associationKey.isKeyColumn(columnName)) {
          row.put(columnName, tuple.get(columnName));
        }
      }

      rows.add(row);
    }
    return rows;
  }
  @Override
  public void updateAssociation(
      Association association,
      AssociationKey associationKey,
      AssociationContext associationContext) {
    List<Map<String, Object>> rows = getAssociationRows(association, associationKey);

    CouchDBAssociation couchDBAssociation =
        ((CouchDBAssociationSnapshot) association.getSnapshot()).getCouchDbAssociation();
    couchDBAssociation.setRows(rows);

    getDataStore().saveDocument(couchDBAssociation.getOwningDocument());
  }