суббота, 9 февраля 2013 г.


Пост 16. Oracle RDBMS External tables, как способ прочитать данные из NoSQL.

Доброго времени суток!
Продолжаю рассказывать об интеграции Oracle NoSQL Database и Oracle RDBMS.
Сегодня речь пойдет о новой возможности появившейся во второй версии Oracle NoSQL database - возможность чтения NoSQL данных из реляционки.
Осуществляется это через механизм Oracle RDBMS External Tables. Если в двух словах внешняя таблица - это технология, которая позволяет читать файл с файловой системы сервера базы данных. Лежит, например, csv файл на серваке, описываю я его в базе данных (create table my_tab_ext ...), а потом могу прочитать эти даные обыкновенным select (очень удобный и быстрый способ загружать данные, например). В Oracle  11.2g добавили пропроцессор. В этом случае,я так же описываю поток данных, только прежде чем прочитать файл могу провеси над ним некие преобразования. Например лежит у меня заархивированный csv, до того как гнать поток данных  в базу, необходимо его распаковать. Все это возможно с помощью препроцессора (в этом случае препроцессором будет команда unzip).
Ноу-хау NoSQL v2 заключается в создании програмы пропроцессора.
Наверное я Вас окончательно запутал? Вот тут действительно лучше один раз увидеть.
Давайте разберем конкретный пример. Наберитесь терпения и шаг за шагом внимательно прочтите последовательность действий.

1) Подготовительный этап - создание дирректорий, назначение прав в RDBMS

-Создание необходимых директорий
SQL> CREATE DIRECTORY ext_tab AS '/home/oracle/nosql/data/';
SQL> CREATE DIRECTORY nosql_bin_dir AS '/home/oracle/nosql/bin/'; 

-Назначение пользователю Oracle RDBMS необходимых прав:
SQL> GRANT READ, WRITE ON DIRECTORY ext_tab TO nosql;
SQL> GRANT READ, EXECUTE ON DIRECTORY nosql_bin_dir TO nosql;

В файл препроцессора nosql_stream прописываем переменные окружения:
export KVHOME= ...
export CLASSPATH= ...

Cам файл необходимо взять из архива дистрибутива Oracle NoSQL Database.
В моем случае я его переложил в /home/oracle/nosql/bin/nosql_stream

2) Подготовим данные в NoSQL базе, которые мы потом будет считывать из Oracle.
Загрузим данные в формате “/profile/Имя/Фамилия/-/phone/:номер телефона” (несколько строчек).
Если не знаете как это делать смотрите вот здесь

3) Cоздайте свой собственный formatter, который будет преобразовывать входную пару ключ-значение в формат внешней таблицы (string с разделителями, указанными при создании внешней таблицы). Java код ниже:


import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import oracle.kv.Key;
import oracle.kv.KeyValueVersion;
import oracle.kv.KVStore;
import oracle.kv.Value;
import oracle.kv.exttab.Formatter;

public class b_NewFormatter implements Formatter {

    private static final String USER_OBJECT_TYPE = "profile";

    public b_NewFormatter() {
    }

    @Override
    public String toOracleLoaderFormat(final KeyValueVersion kvv,
            final KVStore kvStore) {
        final Key key = kvv.getKey();
        final Value value = kvv.getValue();
        final String sValue = new String(value.getValue());

        final List<String> majorPath = key.getMajorPath();
        final List<String> minorPath = key.getMinorPath();

        final String objectType = majorPath.get(0);

        if (!USER_OBJECT_TYPE.equals(objectType)) {
            throw new IllegalArgumentException("Unknown object type: " + key);
        }

        final String Name = majorPath.get(1);
        final String Surname = majorPath.get(2);
        final String atr = minorPath.get(0);

        final StringBuilder sb = new StringBuilder();
        sb.append(Name).append("|");
        sb.append(Surname).append("|");
        sb.append(atr).append("|");
        sb.append(sValue).append("|");
        return sb.toString();

    }

    private String readString(final DataInput in)
            throws IOException {

        if (!in.readBoolean()) {
            return null;
        }

        return in.readUTF();
    }
}


4) В Oracle RDBMS создаем внешнюю таблицу


CREATE TABLE profile_external (name VARCHAR2(64),
                                surname varCHAR2(64),
                                atr VARCHAR2(64),
                                sValue varchar2(256))
        ORGANIZATION EXTERNAL
            (type oracle_loader
             default directory ext_tab
             access parameters (records delimited by newline
             preprocessor nosql_bin_dir:'nosql_stream'
            fields terminated by '|')
       LOCATION ('profile.dat'))
       PARALLEL;

5) Создаем конфигурационный файл для описания NoSQL базы и Oracle
В моем примере:


[oracle@localhost ~]$ cat /home/oracle/nosql/conf/config2.xml
<config version="1">
  <component name="publish" type="params">
    <!-- Fill in appropriate values for
        oracle.kv.exttab.connection.url and oracle.kv.exttab.connection.user
       -->
    <property name="oracle.kv.exttab.connection.url"
              value="jdbc:oracle:thin:/@//localhost:1521/XE"
              type="STRING"/>
    <property name="oracle.kv.exttab.connection.user"
              value="nosql" type="STRING"/>
    <property name="oracle.kv.exttab.tableName" value="profile_external"
              type="STRING"/>
    <!-- If you use a wallet to access your Oracle Instance, uncomment
         this and fill in a suitable value for the

              oracle.kv.exttab.connection.wallet_location

         property. -->
    <!--
    <property name="oracle.kv.exttab.connection.wallet_location"
              value="PATHNAME TO YOUR WALLET DIRECTORY" type="STRING"/>
    -->
  </component>
  <component name="nosql_stream" type="params">
    <!-- Fill in appropriate values for
        oracle.kv.kvstore and oracle.kv.hosts
       -->
    <property name="oracle.kv.kvstore"
              value="kvstore"
              type="STRING"/>
    <property name="oracle.kv.hosts"
              value="LOCALHOST:5000"
              type="STRING"/>
    <property name="oracle.kv.batchSize"
              value="100"
              type="INT"/>
    <property name="oracle.kv.depth"
              value="PARENT_AND_DESCENDANTS"
              type="STRING"/>
    <property name="oracle.kv.parentKey"
              value="/profile"
              type="STRING"/>
    <property name="oracle.kv.formatterClass"
              value="Answers_part3.b_NewFormatter"
              type="STRING"/>
    <!-- Other properties that are not needed for the cookbook example. -->
    <!--
    <property name="oracle.kv.subRange"
              value="I/login/"
              type="STRING"/>
    <property name="oracle.kv.consistency"
              value="tIme(10 seconds, 10 seconds)"
              type="STRING"/>
    <property name="oracle.kv.keyDelimiter"
              value="|"
              type="STRING"/>
    <property name="oracle.kv.variableSizeBytes"
              value="0"
              type="INT"/>
    <property name="oracle.kv.timeout"
              value="10 seconds"
              type="STRING"/>
    -->
  </component>
</config>


6) Используя утилиту publisher создаем конфигурационный файл на который указывает внешняя таблица

[oracle@localhost ~]$ cat /home/oracle/nosql/sh/publish_config.sh
#!/bin/bash
source ~/.bash_profile
java -classpath $KVHOME/lib/*:$ORACLE_HOME/jdbc/lib/ojdbc6.jar oracle.kv.exttab.Publish -config /home/oracle/nosql/conf/config2.xml -publish

7) Добавьте в конфиг препроцессора (/home/oracle/nosql/bin/nosql_stream) путь к новому Formatter.

[oracle@localhost ~]$ cat /home/oracle/nosql/bin/nosql_stream
#!/bin/bash
export PATH=$PATH
export KVHOME=/home/cloudera/nosql/kv-2.0.23
export CLASSPATH=$KVHOME/lib/kvstore-2.0.23.jar:$KVHOME/lib/kvstore-ee-2.0.23.jar:/home/cloudera/nosql/kv-2.0.23/examples/:/home/oracle/nosql/jar/DeveloperDay.jar
/usr/java/jdk1.7.0_02/bin/java oracle.kv.exttab.Preproc $*


8) Пишем SQL для доступа к данным!

select * from profile_external

Вот вроде бы и все. Если внимательно выполнить шаг за шагом здесь описанное - все получится. Если будут вопросы - не стесняйтесь их задавать!

пятница, 8 февраля 2013 г.


Пост 15. Гибридная архитектура. NoSQL + SQL

Когда я только делал первые шаги по дороге NoSQL и Hadoop, мне всегда хотелось посмотреть на них с точки зрения базы данных Oracle, т.к. я всегда был (и остаюсь) верным членом клуба любителей Oracle RDBMS (как можно не любить лучшую реляционную базу в мире)?
Хотелось оставаться в Oracle RDBMS центральной системе мира (в центре всего Oracle, остальное "сателиты"). Теперь это возможно. Начиная со 2 версии Oracle NoSQL database позволяет читать данные из своей базы как из внешней таблицы. Как писалось в моем самом первом посте не стоит злоупотреблять с NoSQL. Надо использовать их только там где это действительно оправдано. Или в тех "кусках" приложения где он подходит. Если вы начинаете новый проект - возможно не стоит выбирать между NoSQL и SQL,просто комбинируйте!
Давайте рассмотрим пример - есть у нас приложение к "крутым" поиском (куча фильттов, релевантность, предиктовые прогнозы и.т.п.). Крутой поиск может с легкостью взять на себя реляционная база данных, а что делать с хранением файлов? Можно конечно засунуть все в эту базу данных... Но получится достаточно дорогое решение... Да и если колличество пользователей будет измеряться десятками тысяч, это тоже будет достаточно проблемно... Тут как раз кстати пришлось бы гибридное решение:

                                             Рис 1. Возможная архитектура.

Итак, представим, что пользователь формирует запрос (через браузер, например): говорит, что хочет фотографии, сделанную определенным фотографом в определенном месте с рейтингом не ниже определенного, ну и еще много чего. Далее этого запрос отправляется на сервер приложений (шаг 1). Сервер приложений обрабатывает его формирует запрос к реляционной базе(шаг 2), которая отработав его возвращает одну колонку типа varchar2 (шаг 3). Приложение формирует на основе возвращенных данных запрос к NoSQL базе (шаг 4), типа: дай мне набор байт по этому ключу. Приложение знает что этот набор байт картинка. Эту картинку он и возвращает клиенту (шаг 5). Вот как то так. Не бойтесь использовать вместе традиционные технлогии и NoSQL!

Далее я расскажу о возможности добраться до NoSQL данных из базы данных Oracle.

Пост 14. Oracle NoSQL Database v2.

"Давненько не брал я в руки шашек!" - говаривал Ноздрев Чичикову. "Давненько ничего я тут не писал" - скажу я Вам. За время моего "молчания" Oracle NoSQL Database разразился второй версией. Вторая версия принесла много приятных сюрпризов. Но обо всем по порядку.

                           
                                          Рис.1 Новшества Oracle NoSQL Database v2.

Итак, по порядку.
1) Масштабируемость и управляемость.
 - Эластичность
Добавлена возможность добавлять "на лету" новые репликационные группы (шарды).
Теперь из вот такогой топологии можно на лету:


сделать вот такую:

- Перебалансировка данных между шардами
Теперь данные с нагруженых шардов могут быть перенесены на менее нагруженые.
Из вот такого расположения:

можно сделать:

2) Новые API
- Добавлено С API
- Добавлен сериализатор AVRO (сериализация value)
- Добавлена поддержка больших объектов (LOB).

3) Интеграция и мониторинг
- Внешние таблицы. Теперь данные из Oracle NoSQL Database можно читать с помощью внешних таблиц Oracle RDBMS.
- Возможность использования Oracle NoSQL Database как источник для OEP (CEP).
- Поддержка SNMP/JMX
- Интеграция с RFD (опция базы данных Oracle)

Далее я буду подробнее описывать все выше описанное!
Успехов всем!

вторник, 25 сентября 2012 г.

Пост 13. Начинаем работу!

Итак, пора уже наконец начать работу с Oracle NoSQL DB
Для этого надо скачать виртуалку.


Для этого надо скачать виртуалку.
К сожалению, в силу лицензионной политики моей компании я не могу выкладывать виртуальные машины в открытый доступ. Поэтому пишите на e-mail: а oracle.nosql@gmail.com, я вышлю инструкции, где будет сказано о том,как ее получить.


После скачивания, собираем(разбивал total commander), запускаем (VmWare), читаем инструкцию и наслаждаемся NoSQL DB!

1) Работу следует начать с переразвертывания базы. Запускаем скрипт
/opt/oracle/ReDeploy.sh
2) Далее запускает IDE NetBeans (ярлык на рабочем столе)
3) Описание пакетов
- Support
Вспомогательный пакет. Содержит 2 класса.
Support.OraStore.java - класс содержит 1 метод, используется для подключения к базе.
На вход подаем имя хранилища, получаем указательна объект БД.

Support.ParseKey.java - класс содержит 1 метод, осуществляет разбор ключа по заданному шаблону.
На вход подается String - отдается указатель на объект типа Key.
пример входных данных: major1/major2/-/minor1 (заметье, major1/major2/-/minor1 - НЕ ВЕРНО )
- CRUD
Пакет, включающий в себя классы, выполняющие CRUD (Create Retrieve Update Delete) операции.
Create. Этот класс предназначен для создание пар ключ-значение в базе. Содержит 3 метода с одинаковыми конструторами.
- putIfPresent - метод записывает пару ключ-значение,если данные есть, если данныех нет - выкидывает exeption.
- putIfAbsent - метод записывает пару ключ-значение,если данных нет, если данные есть - выкидывает exeption.
- put - записыавет пару ключ-значение в любом случае.
   Конструктор (String sKey, String data, KVStore myStore).
sKey - ключ в формате строки (внутри метода происходит парсинг).
пример: major1/major2/-/minor1.
data - значение. Данный метод поддерживает только value типа String.
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.
Retrieve. Этот класс предназначен для извлечения пар ключ-значение из базы.
- SelectRow - метод для извлечения одной стороки.
Конструктор(String sKey, KVStore myStore), возвращает String.
sKey - ключ в формате строки (внутри метода происходит парсинг).
пример: major1/major2/-/minor1.
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.
- SelectAll - метод для извлечения всей базы данных (вывод на экран).
Конструктор(KVStore myStore).
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.
- SelectWhereFullMajor - метод для извлечения множества строк по ПОЛНОМУ major ключу (вывод на экран)
Конструктор(String sKey, KVStore myStore)
sKey - major составляющая ключа
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.
Пример: есть ключи
major1/major2/-/minor1/
major1/major2/-/minor2/
major1/major2/-/minor3/
Их все надо извлечь.
задать в качестве ключа (sKey) необходимо "major1/major2/"
НЕЛЬЗЯ искать по части: "major1"
- SelectWhere - метод для извлечения множества строк по ЧАСТИ major ключа (вывод на экран)
Конструктор(String sKey, KVStore myStore)
sKey - major составляющая ключа
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.
Пример: есть ключи
major1/major2/-/minor1/
major1/major3/-/minor2/
major1/major4/-/minor3/
Их все надо извлечь.
задать в качестве ключа (sKey) необходимо "major1/"
Но метод не работает с полными major ключами

Update. Класс содержит 1 метод: putIfpresent (описание см. выше в классе Create).

Delete. Класс содержит 2 метода.
- ClearStore. Удаление всех данных из базы.
Конструктор(KVStore myStore).
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.
- DeleteKey. Удаление одной пары из базы.
Конструктор(String sKey, KVStore myStore), возвращает String.
sKey - ключ в формате строки (внутри метода происходит парсинг).
пример: major1/major2/-/minor1.
myStore - объект базы даных. Указатель на объект дожен быть создан ранее.


- SocialNetwork
Пакет непосредственно реализующий приложение (как раз таки использует пакеты CRUD и Support). В данном случае - некая соц. сеть
Auth - класс для администрирования и аутентицикации пользователей
- add_admin метод для добавления пользователей
Конструктор(String AdminName, String AdminAtribute, String Pass, KVStore myStore)
AdminName - имя нового пользователя
AdminAtribute - атрибуты нового пользователя (возраст, пол, образование ... )
Pass - пароль нового пользователя
myStore - указатель на объект базы данных (необходимо создать ранее, методу передается лишь указатель)
- check_passwd - аутентификация пользователя. Возвращает String "Yes" или "No"
Конструктор (String AdminName, String AdminPass, KVStore myStore)
AdminName - имя пользователя (логин)
Pass - пароль пользователя
myStore - указатель на объект базы данных (необходимо создать ранее, методу передается лишь указатель)
MessageManagment - класс для управления потоком собщений соц. сети.
- post данный метод осуществляет пост сообщения на стену
Конструктор (String UserName, String text, KVStore myStore)
UserName - пользователь, оставляющий сообщение
text - текст сообщения
myStore - указатель на объект базы данных (необходимо создать ранее, методу передается лишь указатель)
- subscribe_to подписка на сообщения другого пользователя
Конструктор (String User, String IntrestingPerson, KVStore myStore)
User - тот кто подписывается
IntrestingPerson - тот на кого подписываются
myStore - указатель на объект базы данных (необходимо создать ранее, методу передается лишь указатель)
- show_tape метод, отображающий стену (ТОР N сообщений, пользователя и того на кого он подписан, отсортированных по времени)
Конструктор (String User, int tape_depth, KVStore myStore)
User пользователь, чью стену необходимо отрисовать
tape_depth - колличество сообщений которые надо отображать (ТОР N)
myStore - указатель на объект базы данных (необходимо создать ранее, методу передается лишь указатель)

SocialNetwork - main класс проекта.

Если будут вопросы - не стесняйтесь их задавать!

пятница, 17 августа 2012 г.

Пост 12. ACID. Durability.

Едем дальше. Durability. Что это значит? А значит это то, что независимо от проблем на нижних уровнях (к примеру, обесточивание системы или сбои в оборудовании) изменения, сделанные успешно завершённой транзакцией, должны остаться сохранёнными после возвращения системы в работу. Другими словами если пользователь внес данные в вашу систему и почил подтверждение о том, что они успешно записаны, они не должны быть потеряны, вне зависимости ни отчего (пропало питание в ЦОД, посыпался диск...). Ну представьте вы купили электронный авиабилет, вам пришло подтверждение. Тут же посыплся диск на который вы записали свои данные. Приезжаете в аэропорт в солнцезащитных очках, гавайской рубашке и в предвкушении долгожданного пляжного отдыха, а Вам говорят, что данных в системе нет. Ситуация конечно излишне гиперболизирована, но суть думаю ясна.
В контексте Oracle NoSQL это выглядит вот так:



Рис.1. Durability.

Итак, при проектировании приложения нам приходится выбирать между надежностью и скоростью. У нас есть 2 измерения для выбора "золотой середины". Первое - уровень синхронизации - когда данные могут считаться записанными: когда они попали в ОЗУ (самое быстрое), когда из ОЗУ они перешли в буфферный кэш файловой системы, либо когда они попали на диск (самое надежное). Второе измерение это так называемая обратная связь (сколько серверов подтвердило поступление пары ключ-значение). Самое быстрое - "ни одного", то есть пары попали только на мастера, далее следует режим majority (от многих), ну и самым надежным является тот случай, если получение пары подтвердили все сервера репликационной группы. Использовать это API проще простого.
Устанавливаем настройки надежности:

Durability durability =
new Durability (Durability.SyncPolicy.SYNC, Durability.SyncPolicy.SYNC, Durability.ReplicaAckPolicy.ALL);
myStore.put(myKey, myValue,null,durability,30, TimeUnit.SECONDS);

Вот как то так.
Если у вас есть какие-либо вопросы по Oracle NoSQL - задавайте в комментах, постараюсь ответить, либо пишите на oracle.nosql@gmail.com.

среда, 8 августа 2012 г.


Пост 11. ACID. Consistency.

Следующий пункт ACID концепции в рамках данной серии статей - Consistency, согласованность. Система находится в согласованном состоянии до начала транзакции и должна остаться в согласованном состоянии после завершения транзакции.Представьте, что у Вас есть система, состоящая их 2х и более узлов, которые реплицируют одну и туже информацию (попросту говоря копируют). Представьте себе, что вы записали некоторые данные на сервер1 и получили подтверждение успешной записи. Практически в тот же момент другой пользователь запросил данные, которые вы только что записали и не получил их... потому что балансировщик отправил его на сервер2 (куда данные еще не успели среплицироваться). Требование согласованности не выполнено.
Рис.1 Система находится в согласованном состоянии


Рис.2 Система находится в не согласованном состоянии

 А что же мне делать, если я хочу обеспечить выполнене принципа согласованности? И как сказали бы в рекламе Oracle NoSQL летит к Вам!
В начале хотел бы рассказать о том, что такое согласованность в контексте Oracle NoSQL.
Существует несколько типов согласованности (расположены в порядки убывания скорости):
- Согласованность отсутствует (самое быстрое чтение)
- Согласованность по времени
- Согласованность по версии
- Абсолютная согласованность (самое медленное чтение)

Если вы хотите обеспечить согласованное чтение, используйте другой конструктор получения value (get, MultiGet...)

Давайте создадим программу, которая читает одно значение по ключу (аналогичный метод создавался ранее, но в этот раз использовался другой конструктор get)

public static String ConsistencyRead(String sKey, String store, String host, String port) {
OraStore orastore = new OraStore(store, host, port);
String data = null;
KVStore myStore = orastore.getStore();
System.out.println("Store Opened");
Key myKey = ParseKey.ParseKey(sKey);
try {
ValueVersion vv = myStore.get(myKey, Consistency.ABSOLUTE, 0, null);
Value v = vv.getValue();
data = new String(v.getValue());
System.out.println(myKey + " : " + data);
} catch (RequestTimeoutException re) {
System.out.println(re.getTimeoutMs());
} catch (FaultException fe) {
System.out.println("Unknown error");
} catch (NullPointerException ne) {
System.out.println("Key does not exist");
} finally {
myStore.close();
System.out.println("Store Closed");
}
return data;
}


Если у вас есть какие-либо вопросы по Oracle NoSQL - задавайте в комментах, постараюсь ответить, либо пишите на oracle.nosql@gmail.com

понедельник, 6 августа 2012 г.


Пост 10. ACID. Atomicity.

Итак, сейчас хотел бы рассказать про принцип атомарности. Атомарность гарантирует, что никакая транзакция не будет зафиксирована в системе частично. Будут либо выполнены все её подоперации, либо не выполнено ни одной. Итак, все привыкли думать, что NoSQL базы данных это исключительно BASE системы. "Быстрые, но не надежные". Это не так. Oracle NoSQL может соответствовать ACID концепции. Atomicity в данном контексте это будет просто обозначать транзакции. Долго думал как об этом лучше рассказать - решил добавить еще один класс,с исчерпывающими комментариями, в пакет simpleoperation (о нем читай ниже). Надеюсь все понятно :) Если нет - не стеснятесь задавать вопосы в комментариях или писать по адресу oracle.nosql@gmail.com

package simpleoperation;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import oracle.kv.*;

public class ACID {
// Прописываем переменные идентифицирующие базу данных
static String port = "5000";
static String host = "localhost";
static String store = "kvstore";


public static void main(String args[])
// Открываем нашу базу              
OraStore orastore = new OraStore(store,host,port);
KVStore myStore = orastore.getStore();
System.out.println("Store Opened"); 

// Создаем 2 ключа
String Key1 = "key/-/1/";
String Key2 = "key/-/2";
Key myKey1 = ParseKey.ParseKey(Key1);
Key myKey2 = ParseKey.ParseKey(Key2);
// Создаем 2 значения
String data1 = "First value";
String data2 = "Second value";
Value MyValue1 = Value.createValue(data1.getBytes());
Value MyValue2 = Value.createValue(data2.getBytes());
// Создание транзакции начинается с создания объекта OperationFactory.
OperationFactory of = myStore.getOperationFactory();
// Создаем массив под храниение списка наших операций
List<Operation> opList = new ArrayList<>();
// Заполняем его операциями объекта of
opList.add(of.createPutIfAbsent(myKey1, MyValue1));
opList.add(of.createPutIfAbsent(myKey2, MyValue2));
System.out.println("Transaction Created");
try
{
// Запускаем транзакцию
myStore.execute(opList);
System.out.println("Transaction Executed");
}
catch (OperationExecutionException oee)
{
System.out.println("Operation Execution Exception occured " + oee.getMessage());
}
catch (IllegalArgumentException iae)
{
System.out.println("Illegal Argument Exception occured " + iae.getMessage());
}
catch (FaultException fe)
{
System.out.println("Fault Exception occured " + fe.getMessage());
}
}
}

В итоге будут выполнены 2 операции, либо не выполнена ни одна. 
Если у вас есть какие-либо вопросы по Oracle NoSQL - задавайте в комментах, постараюсь ответить, либо пишите на oracle.nosql@gmail.com