Эта секция предоставляет информацию о MySQL NoSQL Connector for JavaScript, ряде адаптеров Node.js для NDB Cluster и MySQL Server, доступных с NDB 7.3.1, которые позволяют написать приложения JavaScript для Node.js с использованием данных MySQL.
Этот соединитель отличается по многим ключевым отношениям от большинства других соединителей MySQL и API. Интерфейс асинхронный, после встроенной модели событий Node.js. Кроме того, это использует модель объекта области для хранения данных. Запросы получают данные в форме полностью порожденных объектов, а не как строки и столбцы.
MySQL Node.js включает 2 драйвера. Драйвер
ndb
получает доступ к
NDB
напрямую, с применением
NDB API (см. главу 2). MySQL Server для него не
нужен. Драйвер mysql
применяет MySQL Server и
зависит от модуля node-mysql
Node.js из
https://github.com/felixge/node-mysql/. Независимо от драйвера не
требуются никакие SQL-операторы, используя Connector for JavaScript, проекты
Node.js используют объекты данных для всех запросов к базе данных.
Эта секция покрывает базовую установку, установку MySQL
JavaScript Connector и его зависимостей. Connector требует
Node.js и NDB Cluster, можно установить их в любом порядке.
Кроме того, mysql-js
требует драйвер
node-mysql
. Сборка Connector также требует,
чтобы у вашей системы был рабочий компилятор C++, такой как
gcc или
Microsoft Visual Studio.
Чтобы поставить все предпосылки для соединителя JavaScript, включая
node-mysql
, необходимо выполнить следующие шаги:
Node.js. Если у вас нет Node.js на вашей системе, можно получить его из http://nodejs.org/download/. В дополнение к исходному коду предварительно построенные двоичные модули и инсталляторы доступны для многих платформ. У многих дистрибутивов Linux также есть Node.js в их хранилищах (вы, возможно, должны добавить альтернативное хранилище в своем диспетчере пакетов).
NDB 7.3.1 требует Node.js 0.7.9 или более ранний из-за зависимости от node-waf. NDB 7.3.2 и позже использует node-gyp (см. https://npmjs.org/package/node-gyp) и должны работать с Node.js 0.8.0 и позже.
Независимо от метода, которым вы получаете Node.js, имейте в виду, что
архитектура версии, которую вы устанавливаете, должна соответствовать
архитектуре двоичных модулей NDB Cluster: вы не можете, например, установить
JavaScript Connector, имея 64-bit Node.js и 32-bit NDB Cluster.
Если вы не знаете архитектуру своей существующей установки Node.js, можно
определить это, проверив значение
global.process.arch
.
NDB Cluster. Если NDB Cluster, включая все заголовки и файлы библиотеки, еще не установлен в системе, установите его (см. NDB Cluster Installation).
Как упомянуто ранее, необходимо удостовериться, что архитектура (32 бита или 64 бита) является той же самой для NDB Cluster и Node.js. Можно проверить архитектуру существующей установки NDB Cluster в выводе ndb_mgm -V.
Драйвер node-mysql.
mysql-js
также требует рабочей установки
node-mysql
с
https://github.com/felixge/node-mysql/. Можно установить драйвер,
используя команду npm install,
посмотрите веб-сайт проекта об идентификаторе пакета и рекомендуемой версии.
Как только требования выполнены, можно найти файлы для установки
соединителя MySQL для JavaScript в каталоге
share/nodejs
установки NDB Cluster.
Если вы установили NDB Cluster как RPM, это
/usr/share/mysql/nodejs
.
Чтобы использовать инструмент
npm, чтобы выполнить установку
лучшего предположения
без любого вмешательства пользователя, перейдите в каталог
share/nodejs
, затем используйте
npm:
shell> npm install .
Заключительный символ точки (.
)
требуется. Обратите внимание на то, что необходимо управлять этой командой в
подкаталоге share/node.js
каталога
установки NDB Cluster.
Можно проверить установку, используя поставляемую тестовую программу.
Это требует управления NDB Cluster, включая MySQL Server с базой данных
test
. Клиент
mysql должен быть в пути.
Чтобы выполнить тесты, перейдите в каталог
test
:
shell> node driver
По умолчанию всеми серверами управляют на местной машине, используя порты
по умолчанию, это может быть изменено, редактируя файл
test/test_connection.js
,
который произведен, управляя набором тестов. Если этот файл не присутствует
(см. Bug #16967624), можно скопировать
share/nodejs/test/lib/test_connection_js
в
каталог test
.
Если вы установили NDB Cluster не по умолчанию,
вы, возможно, должны экспортировать
LD_LIBRARY_PATH
, чтобы позволить набор тестов.
Набор тестов также требует, чтобы база данных
test
была доступна на сервере MySQL.
NDB 7.3.1 также предлагает альтернативный скрипт сборки в
share/node.js/setup
,
это было удалено в NDB 7.3.2 и позже.
Эта секция содержит описания прототипа и другую информацию для MySQL Connector for JavaScript.
Этот класс представляет пакет операций.
Batch extends Context
execute(Function(Objecterror
)callback
);
Выполните пакет. Когда он выполняется, все операции выполняются, отзыв для
каждой операции вызывают, когда та операция выполняется (операции не
выполняются ни в каком конкретном порядке). Функция
execute()
также вызывает
callback
.
Пакет выполняется в контексте текущего состояния сессии: включен autocommit, если транзакция не была начата, это также включает способ блокировки по умолчанию и ключ разделения.
clear();
Очистите этот пакет, не затрагивая операционное состояние. Будучи очищенным, пакет все еще действительный, но все операции, ранее определенные, удалены: это вернуло пакет к чистому состоянию.
Отзывы для любых операций, которые определяются для этого пакета, вызываются с ошибкой при указании, что пакет был очищен.
Эта функция не требует никаких аргументов.
getSession();
Получите сессию, из которой была создан этот пакет.
Эта функция не требует никаких аргументов.
Context
это супертип
Session
и
Batch
. Это содержит функции, которые
выполняются немедленно, если вызвано от сессии, или когда пакет выполняется.
Mynode
действительно имеет любое
понятие о пользователе и не определяет никаких подобных свойств.
find(Functionconstructor
, Objectkeys
, Function(Objecterror
, Objectinstance
[, ...])callback
[, ...]); find(StringtableName
, Objectkeys
, Function(Objecterror
, Objectinstance
[, ...])callback
[, ...]);
Найдите определенный экземпляр на основе значения уникального ключа или первичного ключа.
Можно использовать любую из двух версий этой функции. В первой версии
параметр constructor
это
функция конструктора отображенного объекта области.
Альтернативно можно использовать
tableName
во втором варианте функции.
Для обеих версий find()
keys
может иметь любой тип.
Ключ должен однозначно определить единственную строку в базе данных. Если
keys
простой тип (число или
последовательность), тогда тип параметра должен быть тем же самым типом или
совместим с типом первичного ключа отображенного объекта. Иначе свойства
взяты от параметра и соответствуют именам свойств в отображении. Свойства
первичного ключа используются, если все присутствуют, другие свойства
проигнорированы. Если keys
не может использоваться, чтобы определить первичный ключ, имена свойств,
соответствующие столбцам уникального ключа, используются вместо этого.
Если никакие полные свойства первичного или уникального ключа не найдены,
сообщают об ошибке. Возвращенный объект загружается на основе отображения и
текущего значения в базе данных.
Для многостолбцовых первичных или уникальных ключей должны быть установлены все поля ключа.
load(Objectinstance
, Function(Objecterror
)callback
);
Загрузите определенный экземпляр, согласовав его первичный или уникальный
ключ со строкой базы данных, не создавая новый объект области.
Это в отличие от
find()
, который создает новый
отображенный объект области.
instance
должен иметь его
значение первичного или уникального ключа или набор. Отображенные значения в
объекте загружаются на основе текущего значения в базе данных. Неотображенные
свойства в объекте не изменяются.
Свойства первичного ключа используются, если все присутствуют и все другие свойства проигнорированы, иначе имена свойств, соответствующие столбцам уникального ключа, используются. Если никакие полные свойства первичного или уникального ключа не могут быть найдены, сообщают об ошибке.
Функция callback
вызвана с параметрами, обеспеченными, когда операция закончилась.
error
это объект Node.js
Error
, см.
раздел 5.3.4.
persist(Objectinstance
, Function(Objecterror
)callback
); persist(Functionconstructor
, Objectvalues
, Function(Objecterror
)callback
); persist(StringtableName
, Objectvalues
, Function(Objecterror
)callback
);
Вставьте экземпляр в базу данных, если экземпляр не существует в базе
данных, в этом случае об исключении сообщает функция
callback
.
Сгенерированные значения присутствуют в случае, когда выполняется
callback
is.
Роль экземпляра, который будет сохранен, может быть выполнена любым из трех способов: объектом экземпляра, конструктором с параметрами для отображенного объекта области, или именем таблицы и значениями, которые будут вставлены.
Во всех трех случаях callback
вызвана с параметрами, если таковые имеются, когда операция закончена.
error
это объект Node.js
Error
, см.
раздел 5.3.4.
remove(Objectinstance
, Function(Objecterror
)callback
); remove(Functionconstructor
, Objectkeys
, Function(Objecterror
)callback
); remove(StringtableName
, Objectkeys
, Function(Objecterror
)callback
);
Удалите экземпляр класса из базы данных первичным или уникальным ключом.
Есть три версии remove()
,
они позволяют вам удалять экземпляр, относясь к объекту
instance
, функции
constructor
или по имени таблицы.
Объект instance
должен содержать
значения ключа, которые однозначно определяют единственную строку в базе
данных. Иначе, если keys
поставляемый конструктором функции или именем таблицы простой тип
(Number
или
String
), тогда тип параметра должен иметь тот же
самый тип или тип, совместимый с типом первичного ключа отображенного
объекта. Если keys
не простой тип, свойства взяты от параметра и соответствуют именам свойств в
отображении. Свойства первичного ключа используются, если все присутствуют и
другие свойства проигнорированы. Если
keys
не определяет первичный ключ, имена свойств, соответствующие уникальному
ключу, используются вместо этого. Если никакие полные свойства первичного или
уникального ключа не найдены, сообщают об ошибке
callback
.
Все три версии remove()
вызывают функцию
callback
с параметрами, если
таковые имеются, когда операция завершена.
error
это объект Node.js
Error
, см.
раздел 5.3.4.
update(Objectinstance
, Function(Objecterror
)callback
); update(Functionconstructor
,keys
,values
, Function(Objecterror
)callback
); update(StringtableName
,keys
,values
, Function(Object error)callback
);
Обновите экземпляр в базе данных с поставляемыми
values
не получая его.
Первичный ключ используется, чтобы определить, какой экземпляр обновляется.
Если экземпляр не существует в базе данных, об исключении сообщают в
callback
.
Как с методами, ранее показанными для сохраняющихся экземпляров
и удаления их от базы данных, update()
существует в трех вариантах, которые позволяют вам использовать
instance
как объект, объект
constructor
с
keys
или по
tableName
и
keys
.
Области уникального ключа keys
определяют, который instance
должен быть обновлен. Объект values
предоставляет значения, которые будут обновлены. Если объект
keys
содержит все области,
соответствующие первичному ключу, первичный ключ определяет экземпляр.
В противном случае уникальные ключи выбраны недетерминированным способом.
update()
не может использоваться, чтобы изменить первичный ключ.
save(Objectinstance
, Function(Objecterror
)callback
); save(Functionconstructor
, Objectvalues
, Function(Objecterror
)callback
); save(StringtableName
, Objectvalues
, Function(Objecterror
)callback
);
Сохраните экземпляр в базе данных, не проверяя на существование.
Если экземпляр уже существует, он обновляется (как будто вы использовали
update()
), иначе это создается (как будто использовали
persist()
). Свойство id
экземпляра
используется, чтобы определить, какой экземпляр должен быть сохранен. Как с
update()
, persist()
и
remove()
, этот метод позволяет вам определять экземпляр, используя
объект, конструктор или имя таблицы.
Все три версии save()
вызывают функцию
callback
с любыми параметрами,
когда операция была закончена.
error
это объект Node.js
Error
, см.
раздел 5.3.4.
Boolean isBatch()
Context
также выставляет метод
isBatch()
, который возвращает true, если
Context
это
Batch
и false, если это
Session
. isBatch()
не берет аргументов.
Классы конвертера преобразовывают между типами MySQL и типами данных JavaScript. Если пользователь поставляет конвертер JavaScript, он используется для чтения и записи базы данных.
У конвертеров есть несколько целей, включая следующие:
Преобразовать между типами MySQL
DECIMAL
и предпочтительной
сервисной библиотекой фиксированной точности JavaScript.
Преобразовать между типами MySQL
BIGINT
и предпочтительной
сервисной библиотекой пользователя JavaScript крупных чисел.
Преобразовать в последовательную форму произвольные объекты приложения в символы или столбцы двоичных данных.
ndb бэкэнд также использует конвертеры, чтобы поддержать столбцы
SET
и
ENUM
. mysql бэкэнд не использует их.
Классу Converter
определили интерфейс:
function Converter() {}: Converter.prototype = { "toDB": function(obj
) {}, "fromDB": function(val
) {} };
Converter
должен
осуществить следующие две функции:
toDB(
: Преобразуйте объект приложения
obj
)obj
в форму, которая может быть сохранена в базе данных.
fromDB(
: Преобразуйте значение val
)val
из базы данных в формат объекта приложения.
Каждая функция возвращает результат преобразования.
Вызовы конвертера связаны следующими способами:
При записи к базе данных, сначала вызван зарегистрированный
FieldConverter
, если есть. Позже вызван любой
зарегистрированный TypeConverter
.
Читая от базы данных, сначала вызван зарегистрированный
TypeConverter
, если есть. Позже вызван любой
зарегистрированный FieldConverter
.
Объект Errors
содержит коды ошибок и сообщение, выставленное адаптерами MySQL Node.js.
var Errors; Errors = { /* Standard-defined classes, SQL-99 */ "02000" : "No Data", // connection errors "08000" : "Connection error", "08001" : "Unable to connect to server", "08004" : "Connection refused", // data errors "22000" : "Data error", "22001" : "String too long", "22003" : "Numeric value out of range", "22008" : "Invalid datetime", // Constraint violations // 23000 includes both duplicate primary key and duplicate unique key "23000" : "Integrity Constraint Violation", // misc. errors "25000" : "Invalid Transaction State", "2C000" : "Invalid character set name", "42S02" : "Table not found", "IM001" : "Driver does not support this function", /* Implementation-defined classes (NDB) */ "NDB00" : "Refer to ndb_error for details" };
Этот класс используется, чтобы произвести и получить информацию о сессиях
(объекты
Session
). Чтобы создать экземпляр, используйте функцию Node.js
require()
с именем драйвера:
var nosql = require("mysql-js");
ConnectionProperties
может использоваться,
чтобы восстановить или установить свойства связи для данной сессии.
Можно получить полный набор свойств связи по умолчанию для данного адаптера,
используя конструктор ConnectionProperties
с названием адаптера (последовательность), используемый в качестве значения
nameOrProperties
:
ConnectionProperties(nameOrProperties
);
Можно также создать собственный объект
ConnectionProperties
, поставляя список свойств
и значений к новому объекту ConnectionProperties
вместо названия адаптера. Тогда можно использовать этот объект, чтобы
установить свойства связи для новой сессии, как показано здесь:
var NdbConnectionProperties = { "implementation" : "ndb", "ndb_connectstring" : "localhost:1186", "database": "test", "mysql_user": "root", "ndb_connect_retries" : 4, "ndb_connect_delay" : 5, "ndb_connect_verbose" : 0, "linger_on_close_msec": 500, "use_ndb_async_api" : false, "ndb_session_pool_min" : 4, "ndb_session_pool_max" : 100, }; var sharePath = '/usr/local/mysql/share/nodejs'; // path to share/nodejs var nosql = require(sharePath); var dbProperties = nosql.ConnectionProperties(NdbConnectionProperties);
Также возможно получить объект со свойствами связи адаптера по умолчанию, после которых можно обновить отобранное количество этих свойств, а затем использовать измененный объект, чтобы установить свойства связи для сессии, как показано здесь:
var sharePath = '/usr/local/mysql/share/nodejs'; // path to share/nodejs var spi = require(sharePath + "/Adapter/impl/SPI"); // under share/nodejs var serviceProvider = spi.getDBServiceProvider('ndb'); var NdbConnectionProperties = serviceProvider.getDefaultConnectionProperties(); NdbConnectionProperties.mysql_user = 'nodejs_user'; NdbConnectionProperties.database = 'my_nodejs_db'; var dbProperties = nosql.ConnectionProperties(NdbConnectionProperties);
Объект ConnectionProperties
включает следующие свойства:
implementation
: Для приложений
Node.js, использующих NDB Cluster, это всегда ndb.
ndb_connectstring
: Строка подключения NDB
Cluster для соединения с сервером управления.
database
: Название базы данных
MySQL, чтобы использовать.
mysql_user
: Имя пользователя MySQL.
ndb_connect_retries
: Сколько раз, чтобы
повторить неудавшуюся связь до тайм-аута, используйте число меньше 0 для
этого значения, чтобы продолжать пробовать связь без остановки.
ndb_connect_delay
:
Интервал в секундах между повторениями связи.
ndb_connect_verbose
: 1 или 0: 1
позволяет дополнительный вывод консоли во время связи.
linger_on_close_msec
:
Когда клиент закрывает DBConnectionPool
,
основная связь сохранена открытой этого число миллисекунд в случае, если
другой клиент попытается использовать ее.
use_ndb_async_api
: Если true, некоторые
операции выполняются, используя асинхронные вызовы, чтобы улучшить
параллельность. Если false, количество операций ограничивается одной
на рабочий поток.
ndb_session_pool_min
: Минимум объектов
DBSession
на
NdbConnectionPool
.
ndb_session_pool_max
: Максимум объектов
DBSession
на
NdbConnectionPool
.
Каждый NdbConnectionPool
обслуживает пул
DBSession
объектов, наряду с их основными
Ndb
объектами.
Этот параметр вместе с ndb_session_pool_min
задает рекомендации для размера этого пула.
Конструктор
TableMapping
также видим как функция
верхнего уровня. Можно получить отображение по имени или при
помощи существующего отображения:
TableMapping(tableName
); TableMapping(tableMapping
);
openSession(properties
,mappings
, Function(err
, Session)callback
);
Соединитесь с источником данных и получите
Session
в функции callback
.
Это эквивалентно запросу connect()
(см. позже в
этой секции), а затем запросу getSession()
в
SessionFactory
, который возвращен в
функции обратного вызова.
Выполнение этого метода могло привести к связям, установленным со многими другими узлами в сети, ждущими их, чтобы стать готовыми, и обращающимися с многократными запросами. Необходимо избежать открывать излишние новые сессии.
Участник внедрения объекта
properties
определяет внедрение
Session
.
Если mappings
не определен, null
или пустой массив, никакие отображения не загружены. В этом случае любые
необходимые отображения загружены при необходимости во время выполнения. Если
mappings
содержит последовательность или функцию конструктора, метаданные для таблицы
(или отображение таблицы) загружены от базы данных и проверены
для требований отображения.
Многократные таблицы и конструкторы могут быть переданы
openSession()
как элементы во множестве.
connect(properties
,mappings
, Function(err
, SessionFactory)callback
);
Соединитесь с источником данных, чтобы получить
SessionFactory
в функции
callback
. Чтобы получить
Session
, необходимо вызвать getSession()
на этой SessionFactory
, чье внедрение
определяется участником внедрения объекта
properties
.
Если mappings
не определена,
null или пустой массив, никакие отображения не загружены.
В этом случае любые необходимые отображения загружены при необходимости. Если
mappings
содержит последовательность или функцию конструктора, метаданные для таблицы
(или отображения таблицы) загружены из базы данных и проверены
для требований отображения.
Многократные таблицы и конструкторы могут быть переданы как элементы во множестве.
Array getOpenSessionFactories()
Получите множество всех объектов
SessionFactory
, которые были
созданы этим модулем.
Следующие функции часть API, но не предназначаются для прикладного
использования. Они являются частью взаимодействия между
Mynode
и
SessionFactory
.
Connection()
getConnectionKey()
getConnection()
newConnection()
deleteFactory()
Сессия это путь доступа основного пользователя к базе данных.
Класс Session
моделирует такую сессию.
Session extends Context
getMapping(Objectparameter
, Function(Objecterr
, Objectmapping
)callback
);
Получите отображения для таблицы или класса.
parameter
может быть именем таблицы, отображенной функцией конструктора или объектом
области. Эта функция возвращает полностью решенный объект
TableMapping
.
Batch createBatch()
Создает новый пустой пакет для сбора многократных операций, которые будут выполнены вместе. В приложении можно вызвать эту функцию так, как показывают здесь:
var nosql = require("mysql-js"); var myBatch = nosql.createBatch();
Array listBatches():
Возвратите множество, элементы которого состоят из всех текущих партий, принадлежащих этой сессии.
Transaction currentTransaction();
Получите текущий объект Transaction
.
void close(Function(Objecterror
)callback
);
Закройте эту сессию. Должна быть вызвана, когда сессия больше не необходима.
boolean isClosed();
Вернет true, если эта сессия закрывается.
void setLockMode(String lockMode
);
Установите способ блокировки для операций чтения. Это немедленно вступает
в силу и остается в силе, пока сессия не закрывается, или этот метод не
вызывают снова. lockMode
это
'EXCLUSIVE'
,
'SHARED'
или
'NONE'
.
Array listTables(databaseName
,callback
);
Перечислите все таблицы в базе данных
databaseName
.
TableMetadata getTableMetadata(StringdatabaseName
, StringtableName
,callback
);
Получите метаданные для таблицы
tableName
в базе данных
databaseName
.
Этот класс используется, чтобы произвести и управлять сессиями.
Session
обеспечивает контекст для транзакций базы данных и
операций. У каждого независимого пользователя должна быть
его собственная сессия.
openSession(Objectmappings
, Function(Objecterror
, Sessionsession
)callback
);
Откройте объект сессии базы данных. Таблица
mappings
утверждена в начале сессии. Ресурсы, требуемые для сессий, ассигнуются
заранее, если те ресурсы не доступны, метод возвращает ошибку в отзыве.
Array getOpenSessions();
Получите все открытые сессии, которые были созданы этой
SessionFactory
.
close(Function(Error err
));
Закройте связь с базой данных. Это гарантирует надлежащее разъединение. Переданная функция вызвана, когда операция закрытия завершена.
TableMapping
описывает отображение объекта области в применении к таблице, хранимой в базе
данных. Отображение таблицы default
это то, которое отображает каждую колонку в таблице к области с
тем же самым именем.
TableMapping = { String table:"" , String database :"" , boolean mapAllColumns : true, Array fields: null };
Члены table
и
data
это названия таблицы и базы данных,
соответственно. mapAllColumns
, если true,
создает
FieldMapping
по умолчанию
для всех колонок, не перечисленных в fields
,
таким образом, что этим всем колонкам, не отображенным явно, дают отображение
по умолчанию области с тем же самым именем.
fields
хранит множество объектов
FieldMapping
, это может также быть единственным
FieldMapping
.
FieldMapping
описывает единственную область в
объекте области. Нет никакого публичного конструктора для этого объекта,
можно создать FieldMapping, используя
TableMapping.mapField()
, или можно использовать
литералы FieldMapping
непосредственно в
конструкторе TableMapping
.
FieldMapping = { String fieldName :"" , String columnName:"" , Boolean persistent: true, Converter converter : null };
fieldName
и
columnName
это
названия поля и колонки, где эта область сохранена, соответственно, в объекте
области. Если persistent
= true (по умолчанию),
область сохранена в базе данных. converter
определяет класс
Converter
, если есть, чтобы использовать с
этой областью (по умолчанию пустой указатель).
Конструктор TableMapping
может взять любое название таблицы (возможно квалифицированное с именем базы
данных) или литерал TableMapping
.
TableMapping mapField(StringfieldName
, [StringcolumnName
], [Converterconverter
], [Booleanpersistent
])
Создайте отображение области для названной области отображенного объекта.
Единственный обязательный параметр это
fieldName
, который предоставляет имя области в объекте приложения
JavaScript. Остающиеся параметры дополнительные и могут появиться в любом
порядке. Текущий объект TableMapping
возвращен.
columnName
определяет название колонки базы данных, которая отображена к этому полю
объекта. Если опущено, columnName
отображено к тому же самому значению, как
fieldName
.
converter
может использоваться, чтобы поставлять класс
Converter
, который выполняет преобразование между типами данных базы данных
и JavaScript. По умолчанию null. persistent
определяет, сохранена ли область в базе данных,
по умолчанию true.
Если persistent
= false, то
columnName
и
converter
не могут использоваться.
TableMapping applyToClass(Function constuctor
)
Присоедините TableMapping
к
constructor
для отображенных
объектов. После того, как это сделано, любой объект, созданный от
конструктора, будет характеризоваться как отображенный экземпляр,
с которым несколько форм соответствующего метода
Session
и
Batch
могут использоваться.
Например, приложение может построить экземпляр, который только частично
полон, затем использовать
Session.load()
, чтобы наполнить его всеми отображенными
областями от базы данных. После того, как приложение изменяет экземпляр,
Session.save()
запишет его назад. Точно так же
Session.find()
может взять отображенного конструктора,
получить объект, основанный на ключах, а затем использовать конструктор,
чтобы создать полный объект области.
Объект TableMetadata
представляет таблицу. Это объект, возвращенный в отзыве
getTable()
.
indexes[0]
представляет внутренний
первичный ключ таблицы.
TableMetadata = { database : "", // Database name name : "", // Table Name columns: {}, // ordered array of ColumnMetadata objects indexes: {}, // array of IndexMetadata objects partitionKey : {}, // ordered array of column numbers in the partition key };
Объект ColumnMetadata
представляет столбец таблицы.
ColumnMetadata = { /* Required Properties */ name : "", // column name columnNumber : -1, // position of column in table, and in columns array columnType : "", // a ColumnTypes value isIntegral : false , // true if column is some variety of INTEGER type isNullable : false , // true if NULLABLE isInPrimaryKey : false , // true if column is part of PK isInPartitionKey : false , // true if column is part of partition key columnSpace: 0 , // buffer space required for encoded stored value defaultValue : null, // default value for column: null for default NULL; // undefined for no default; or a type-appropriate // value for column /* Optional Properties, depending on columnType */ /* Group A: Numeric */ isUnsigned : false , //true for UNSIGNED intSize: null, //1,2,3,4, or 8 if column type is INT scale: 0 , //DECIMAL scale precision: 0 , //DECIMAL precision isAutoincrement: false , //true for AUTO_INCREMENT columns /* Group B: Non-numeric */ length : 0 , //CHAR or VARCHAR length in characters isBinary : false , //true for BLOB/BINARY/VARBINARY charsetNumber: 0 , //internal number of charset charsetName: "", //name of charset };
Объект IndexMetadata
представляет индекс таблицы. Массив indexes
из
TableMetadata
содержит объект
IndexMetadata
на индекс таблицы.
NDB
осуществляет первичный ключ как заказанный и как уникальный индекс, и мог бы
быть рассмотрен через адаптер API NDB как два индекса, но через адаптер MySQL
как единственный индекс, который уникален и заказан. Мы терпим это
несоответствие и отмечаем, что внедрение в
Adapter/api
должно рассматривать эти два описания как эквивалентные.
IndexMetadata = { name : "", // Index name; undefined for PK isPrimaryKey : true, // true for PK; otherwise undefined isUnique : true, // true or false isOrdered: true, // true or false; can scan if true columns: null, // an ordered array of column numbers };
Объекты ColumnMetaData
columnType
должны быть действительными
значениями ColumnTypes
,
как показано в определении этого объекта здесь:
ColumnTypes =["TINYINT", "SMALLINT", "MEDIUMINT", "INT", "BIGINT", "FLOAT", "DOUBLE", "DECIMAL", "CHAR", "VARCHAR", "BLOB", "TEXT", "DATE", "TIME", "DATETIME", "YEAR", "TIMESTAMP", "BIT", "BINARY", "VARBINARY"];
Транзакция всегда автоматическая или явная. Если она автоматическая (autocommit), каждая операция выполняется как часть новой транзакции, которая автоматически передается.
begin();
Начните транзакцию. Никакие аргументы не требуются. Если транзакция уже активна, исключение брошено.
commit(Function(Objecterror
)callback
);
Передайте транзакцию.
Этот метод берет в качестве собственного аргумента функцию
callback
, которая
возвращает ошибочный объект.
rollback(Function(Objecterror
)callback
);
Отмените транзакцию. Об ошибках сообщают в функции
callback
.
Boolean isActive();
Определите, активна ли в настоящее время данная транзакция. Вернет true, если транзакция активная, и false иначе.
isActive()
не требует никаких аргументов.
setRollbackOnly();
Отметьте транзакцию как только для обратной перемотки. Как только это
сделано, commit()
отменяет транзакцию
и бросает исключение, rollback()
отменяет
транзакцию, но не бросает исключение. Чтобы отметить транзакцию как только
для обратной перемотки, вызовите метод
setRollbackOnly()
.
Этот метод односторонний, транзакция, отмеченная как только для обратной
перемотки, не может быть разотмечена.
Вызов setRollbackOnly()
в режиме autocommit
бросит исключение. Этот метод не требует никаких аргументов.
boolean getRollbackOnly();
Определите, была ли транзакция отмечена как только для обратной перемотки.
Вернет true, если транзакция была так отмечена.
setRollbackOnly()
не берет аргументов.
Эта секция содержит много примеров, выполняющих основные операции по базе
данных, такие как получение, вставка или удаление строк таблицы.
Исходные тексты этих файлов также можно найти в
share/nodejs/samples
в каталоге
установки NDB Cluster.
Требования к программному обеспечению для примеров в следующих нескольких секциях следующие:
Работающая установка Node.js.
Рабочие установки ndb
и
mysql-js
.
Адаптер mysql-js
также требует рабочей
установки драйвера node-mysql
из
https://github.com/felixge/node-mysql/.
Раздел 5.2 описывает процесс установки для всех этих требований.
База данных-образец, таблица и данные.
Все примеры используют типовую таблицу tweet
в базе данных test
. Эта таблица определяется как
в следующем CREATE TABLE
:
CREATE TABLE IF NOT EXISTS tweet(id CHAR(36) NOT NULL PRIMARY KEY, author VARCHAR(20), message VARCHAR(140), date_created TIMESTAMP, KEY idx_btree_date_created (date_created), KEY idx_btree_author(author)) ENGINE=NDB;
Таблица tweet
может быть составлена запуском
SQL-скрипта create.sql
в клиенте
mysql. Можно сделать это,
вызвав mysql
в системной оболочке, как показано здесь:
shell> mysql < create.sql
Все примеры также используют два модуля, определенные в файле
lib.js
, чье содержание воспроизводится здесь:
# FILE: lib.js "use strict"; var udebug = unified_debug.getLogger("samples/lib.js"); var exec = require("child_process").exec; var SQL = {}; /* Pseudo random UUID generator */ var randomUUID = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8); return v.toString(16); }); }; /* Tweet domain object model */ var Tweet = function(author, message) { this.id = randomUUID(); this.date_created = new Date(); this.author = author; this.message = message; }; /* SQL DDL Utilities */ var runSQL = function(sqlPath, source, callback) { function childProcess(error, stdout, stderr) { udebug.log('harness runSQL process completed.'); udebug.log(source + ' stdout: ' + stdout); udebug.log(source + ' stderr: ' + stderr); if (error !== null) { console.log(source + 'exec error: ' + error); } else { udebug.log(source + ' exec OK'); } if (callback) { callback(error); } } var p = mysql_conn_properties; var cmd = 'mysql'; if (p) { if (p.mysql_socket) { cmd += " --socket=" + p.mysql_socket; } else if (p.mysql_port) { cmd += " --port=" + p.mysql_port; } if (p.mysql_host) { cmd += " -h " + p.mysql_host; } if (p.mysql_user) { cmd += " -u " + p.mysql_user; } if (p.mysql_password) { cmd += " --password=" + p.mysql_password; } } cmd += ' <' + sqlPath; udebug.log('harness runSQL forking process...'); var child = exec(cmd, childProcess); }; SQL.create = function(suite, callback) { var sqlPath = path.join(suite.path, 'create.sql'); udebug.log_detail("createSQL path: " + sqlPath); runSQL(sqlPath, 'createSQL', callback); }; SQL.drop = function(suite, callback) { var sqlPath = path.join(suite.path, 'drop.sql'); udebug.log_detail("dropSQL path: " + sqlPath); runSQL(sqlPath, 'dropSQL', callback); }; /* Exports from this module */ exports.SQL = SQL; exports.Tweet = Tweet;
Наконец, модуль, используемый для случайного создания данных, включен в
файл ndb_loader/lib/RandomData.js
:
# FILE: RandomData.js var assert = require("assert"); function RandomIntGenerator(min, max) { assert(max > min); var range = max - min; this.next = function() { var x = Math.floor(Math.random() * range); return min + x; }; } function SequentialIntGenerator(startSeq) { var seq = startSeq - 1; this.next = function() { seq += 1; return seq; }; } function RandomFloatGenerator(min, max, prec, scale) { assert(max > min); this.next = function() { var x = Math.random(); /* fixme! */ return 100 * x; }; } function RandomCharacterGenerator() { var intGenerator = new RandomIntGenerator(32, 126); this.next = function() { return String.fromCharCode(intGenerator.next()); }; } function RandomVarcharGenerator(length) { var lengthGenerator = new RandomIntGenerator(0, length), characterGenerator = new RandomCharacterGenerator(); this.next = function() { var i = 0, str = "", len = lengthGenerator.next(); for (; i < len ; i++) str += characterGenerator.next(); return str; } } function RandomCharGenerator(length) { var characterGenerator = new RandomCharacterGenerator(); this.next = function() { var i = 0, str = ""; for(; i < length ; i++) str += characterGenerator.next(); return str; }; } function RandomDateGenerator() { var generator = new RandomIntGenerator(0, Date.now()); this.next = function() { return new Date(generator.next()); }; } function RandomGeneratorForColumn(column) { var g = {}, min, max, bits; switch(column.columnType.toLocaleUpperCase()) { case "TINYINT": case "SMALLINT": case "MEDIUMINT": case "INT": case "BIGINT": if (column.isInPrimaryKey) { g = new SequentialIntGenerator(0); } else { bits = column.intSize * 8; max = column.isUnsigned ? Math.pow(2,bits)-1 : Math.pow(2, bits-1); min = column.isUnsigned ? 0 : 1 - max; g = new RandomIntGenerator(min, max); } break; case "FLOAT": case "DOUBLE": case "DECIMAL": g = new RandomFloatGenerator(0, 100000); // fixme break; case "CHAR": g = new RandomCharGenerator(column.length); break; case "VARCHAR": g = new RandomVarcharGenerator(column.length); break; case "TIMESTAMP": g = new RandomIntGenerator(0, Math.pow(2,32)-1); break; case "YEAR": g = new RandomIntGenerator(1900, 2155); break; case "DATE": case "TIME": case "DATETIME": g = new RandomDateGenerator(); break; case "BLOB": case "TEXT": case "BIT": case "BINARY": case "VARBINARY": default: throw("UNSUPPORTED COLUMN TYPE " + column.columnType); break; } return g; } function RandomRowGenerator(table) { var i = 0, generators = []; for (; i < table.columns.length ; i++) { generators[i] = RandomGeneratorForColumn(table.columns[i]); } this.newRow = function() { var n, col, row = {}; for (n = 0; n < table.columns.length ; n++) { col = table.columns[n]; row[col.name] = generators[n].next(); } return row; }; } exports.RandomRowGenerator = RandomRowGenerator; exports.RandomGeneratorForColumn = RandomGeneratorForColumn;
# FILE: find.js var nosql = require('..'); var lib = require('./lib.js'); var adapter = 'ndb'; global.mysql_conn_properties = {}; var user_args = []; // *** program starts here *** // analyze command line var usageMessage = "Usage: node find key\n" + " -h or --help: print this message\n" + " -d or --debug: set the debug flag\n" + " --mysql_socket=value: set the mysql socket\n" + " --mysql_port=value: set the mysql port\n" + " --mysql_host=value: set the mysql host\n" + " --mysql_user=value: set the mysql user\n" + "--mysql_password=value: set the mysql password\n" + " --detail: set the detail debug flag\n" + " --adapter=<adapter>: run on the named adapter (e.g. ndb or mysql)\n" ; // handle command line arguments var i, exit, val, values; for (i = 2; i < process.argv.length ; i++) { val = process.argv[i]; switch (val) { case '--debug': case '-d': unified_debug.on(); unified_debug.level_debug(); break; case '--detail': unified_debug.on(); unified_debug.level_detail(); break; case '--help': case '-h': exit = true; break; default: values = val.split('='); if (values.length === 2) { switch (values[0]) { case '--adapter': adapter = values[1]; break; case '--mysql_socket': mysql_conn_properties.mysql_socket = values[1]; break; case '--mysql_port': mysql_conn_properties.mysql_port = values[1]; break; case '--mysql_host': mysql_conn_properties.mysql_host = values[1]; break; case '--mysql_user': mysql_conn_properties.mysql_user = values[1]; break; case '--mysql_password': mysql_conn_properties.mysql_password = values[1]; break; default: console.log('Invalid option ' + val); exit = true; } } else { user_args.push(val); } } } if (user_args.length !== 1) { console.log(usageMessage); process.exit(0); }; if (exit) { console.log(usageMessage); process.exit(0); } console.log('Running find with adapter', adapter, user_args); //create a database properties object var dbProperties = nosql.ConnectionProperties(adapter); // create a basic mapping var annotations = new nosql.TableMapping('tweet').applyToClass(lib.Tweet); //check results of find var onFind = function(err, object) { console.log('onFind.'); if (err) { console.log(err); } else { console.log('Found: ' + JSON.stringify(object)); } process.exit(0); }; // find an object var onSession = function(err, session) { if (err) { console.log('Error onSession.'); console.log(err); process.exit(0); } else { session.find(lib.Tweet, user_args[0], onFind); } }; // connect to the database nosql.openSession(dbProperties, annotations, onSession);
# FILE: insert.js var nosql = require('..'); var lib = require('./lib.js'); var adapter = 'ndb'; global.mysql_conn_properties = {}; var user_args = []; // *** program starts here *** // analyze command line var usageMessage = "Usage: node insert author message\n" + " -h or --help: print this message\n" + " -d or --debug: set the debug flag\n" + " --mysql_socket=value: set the mysql socket\n" + " --mysql_port=value: set the mysql port\n" + " --mysql_host=value: set the mysql host\n" + " --mysql_user=value: set the mysql user\n" + "--mysql_password=value: set the mysql password\n" + " --detail: set the detail debug flag\n" + " --adapter=<adapter>: run on the named adapter (e.g. ndb or mysql)\n" ; // handle command line arguments var i, exit, val, values; for (i = 2; i < process.argv.length ; i++) { val = process.argv[i]; switch (val) { case '--debug': case '-d': unified_debug.on(); unified_debug.level_debug(); break; case '--detail': unified_debug.on(); unified_debug.level_detail(); break; case '--help': case '-h': exit = true; break; default: values = val.split('='); if (values.length === 2) { switch (values[0]) { case '--adapter': adapter = values[1]; break; case '--mysql_socket': mysql_conn_properties.mysql_socket = values[1]; break; case '--mysql_port': mysql_conn_properties.mysql_port = values[1]; break; case '--mysql_host': mysql_conn_properties.mysql_host = values[1]; break; case '--mysql_user': mysql_conn_properties.mysql_user = values[1]; break; case '--mysql_password': mysql_conn_properties.mysql_password = values[1]; break; default: console.log('Invalid option ' + val); exit = true; } } else { user_args.push(val); } } } if (user_args.length !== 2) { console.log(usageMessage); process.exit(0); }; if (exit) { console.log(usageMessage); process.exit(0); } console.log('Running insert with adapter', adapter, user_args); //create a database properties object var dbProperties = nosql.ConnectionProperties(adapter); // create a basic mapping var annotations = new nosql.TableMapping('tweet').applyToClass(lib.Tweet); //check results of insert var onInsert = function(err, object) { console.log('onInsert.'); if (err) { console.log(err); } else { console.log('Inserted: ' + JSON.stringify(object)); } process.exit(0); }; // insert an object var onSession = function(err, session) { if (err) { console.log('Error onSession.'); console.log(err); process.exit(0); } else { var data = new lib.Tweet(user_args[0], user_args[1]); session.persist(data, onInsert, data); } }; // connect to the database nosql.openSession(dbProperties, annotations, onSession);
FILE: delete.js var nosql = require('..'); var lib = require('./lib.js'); var adapter = 'ndb'; global.mysql_conn_properties = {}; var user_args = []; // *** program starts here *** // analyze command line var usageMessage = "Usage: node delete message-id\n" + " -h or --help: print this message\n" + " -d or --debug: set the debug flag\n" + " --mysql_socket=value: set the mysql socket\n" + " --mysql_port=value: set the mysql port\n" + " --mysql_host=value: set the mysql host\n" + " --mysql_user=value: set the mysql user\n" + "--mysql_password=value: set the mysql password\n" + " --detail: set the detail debug flag\n" + " --adapter=<adapter>: run on the named adapter (e.g. ndb or mysql)\n" ; // handle command line arguments var i, exit, val, values; for(i = 2; i < process.argv.length ; i++) { val = process.argv[i]; switch (val) { case '--debug': case '-d': unified_debug.on(); unified_debug.level_debug(); break; case '--detail': unified_debug.on(); unified_debug.level_detail(); break; case '--help': case '-h': exit = true; break; default: values = val.split('='); if (values.length === 2) { switch (values[0]) { case '--adapter': adapter = values[1]; break; case '--mysql_socket': mysql_conn_properties.mysql_socket = values[1]; break; case '--mysql_port': mysql_conn_properties.mysql_port = values[1]; break; case '--mysql_host': mysql_conn_properties.mysql_host = values[1]; break; case '--mysql_user': mysql_conn_properties.mysql_user = values[1]; break; case '--mysql_password': mysql_conn_properties.mysql_password = values[1]; break; default: console.log('Invalid option ' + val); exit = true; } } else { user_args.push(val); } } } if (user_args.length !== 1) { console.log(usageMessage); process.exit(0); }; if (exit) { console.log(usageMessage); process.exit(0); } console.log('Running delete with adapter', adapter, user_args); //create a database properties object var dbProperties = nosql.ConnectionProperties(adapter); // create a basic mapping var annotations = new nosql.TableMapping('tweet').applyToClass(lib.Tweet); // check results of delete var onDelete = function(err, object) { console.log('onDelete.'); if (err) { console.log(err); } else { console.log('Deleted: ' + JSON.stringify(object)); } process.exit(0); }; // delete an object var onSession = function(err, session) { if (err) { console.log('Error onSession.'); console.log(err); process.exit(0); } else { var tweet = new lib.Tweet(); tweet.id = user_args[0]; session.remove(tweet, onDelete, user_args[0]); } }; // connect to the database nosql.openSession(dbProperties, annotations, onSession);