Статьи

Что нового в JDO 2.3

Объекты данных Java (JDO) — это спецификация для персистентности Java, которая началась в 2000 году с двумя основными выпусками JDO1 (2002 под JSR0012) и JDO2 (2006 под JSR0243). Он был помещен под Apache в 2005 году и является редким примером спецификации, которая постоянно совершенствовалась в течение своей жизни, в течение последних 4 лет, полностью разрабатываемой в открытом доступе, принимая мнения всех. Совсем недавно он был предоставлен как неотъемлемая часть Google AppEngine для Java.

JDO 2.3 был запущен в октябре 2008 года и включает в себя дополнения к спецификации в областях API метаданных, API-расширителя, добавление управления отменой / тайм-аутом к запросам и добавление управления блокировкой объектов при чтении.

Недавно была выпущена DataNucleus AccessPlatform 1.1.3 с поддержкой этих новых функций, а Apache JDO только что выпустил JDO 2.3 «ранний доступ». В этой статье мы расскажем о том, что нового, и кратко о том, как его использовать.

 

API метаданных

Для сохранения объектов Java вам необходимо указать, какие классы являются постоянными и как они сохраняются. Это было традиционно обработано с использованием конфигурации XML. С появлением JDK1.5 аннотации были добавлены в качестве еще одного возможного способа определения такой информации. JDO 2.3 идет дальше и предоставляет API-интерфейс метаданных , позволяющий определять время выполнения. Это особенно полезно для систем, которые не знают при запуске приложения, какие классы должны быть сохраняемыми, возможно, потому что класс еще не написан.

Чтобы продемонстрировать API метаданных, давайте предположим, что у нас есть хранилище PersistenceManagerFactory, созданное для нашего хранилища данных. Поэтому мы запрашиваем новый объект метаданных.

PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory(props);
JDOMetaData jdomd = pmf.newMetadata();

Теперь мы можем начать определять метаданные для пакета / класса (классов), которые мы хотим сохранить. Метаданные структурированы аналогично XML DTD / XSD. Итак, давайте добавим класс

ClassMetadata cmd = jdomd.newClassMetadata("test.Client");
cmd.setTable("CLIENT").setDetachable(true).setIdentityType(javax.jdo.annotations.IdentityType.DATASTORE);
cmd.setPersistenceModifier(javax.jdo.metadata.ClassPersistenceModifier.PERSISTENCE_CAPABLE);

Итак, у нас есть класс test.Client, использующий идентификатор хранилища данных, который является отсоединяемым и сохраняется в таблице CLIENT . Как видите, вы можете устанавливать цепочки для удобного кодирования.

InheritanceMetadata inhmd = cmd.newInheritanceMetadata();
inhmd.setStrategy(javax.jdo.annotations.InheritanceStrategy.NEW_TABLE);
DiscriminatorMetadata dmd = inhmd.newDiscriminatorMetadata();
dmd.setColumn("disc").setValue("Client").setStrategy(javax.jdo.annotations.DiscriminatorStrategy.VALUE_MAP);
dmd.setIndexed(Indexed.TRUE);

VersionMetadata vermd = cmd.newVersionMetadata();
vermd.setStrategy(javax.jdo.annotations.VersionStrategy.VERSION_NUMBER).setColumn("version");
vermd.setIndexed(Indexed.TRUE);

Таким образом, мы будем использовать наследование «новой таблицы» для этого класса, и у него будет дискриминатор, хранящийся в колонке диска типа «value-map». Класс также будет версионным, используя версию столбца , которая проиндексирована. Все это было для класса в целом, поэтому давайте посмотрим на поля / свойства класса.

FieldMetadata fmd = cmd.newFieldMetadata("name");
fmd.setNullValue(javax.jdo.annotations.NullValue.DEFAULT).setColumn("name").setIndexed(true).setUnique(true);

Таким образом, у нас есть имя поля , которое сохраняется в имени столбца , является уникальным и индексируется. Все компоненты метаданных API следуют DTD, как указано ранее, поэтому, если бы наше поле было коллекцией, мы могли бы определить CollectionMetadata под ним.

Осталось только зарегистрировать метаданные в PersistenceManagerFactory, как это

pmf.registerMetadata(jdomd);

и любой контакт с классом теперь будет сохраняться в соответствии с этими метаданными.

Вы также можете просматривать уже зарегистрированные метаданные, используя

ComponentMetadata compmd = pmf.getMetadata("mydomain.MyClass");

Обратите внимание, что вы не можете изменить уже зарегистрированные метаданные с помощью JDO 2.3. Вы можете просмотреть Javadocs для Metadata API здесь .

 

Enhancer API

Реализации JDO обычно (но не обязаны) включают этап улучшения байт-кода, позволяющий эффективно обнаруживать изменения объектов. Хотя API-интерфейс метаданных выше очень полезен, если мы просто определяем метаданные для класса, нам все же необходимо улучшить класс с помощью этих метаданных. Здесь вступает API Enhancer . Для начала нам нужно получить JDOEnhancer

JDOEnhancer enhancer = JDOHelper.getEnhancer();

и теперь, когда у нас есть энхансер и мы хотим улучшить наш класс выше, нам нужно зарегистрировать в нем наши новые метаданные (сгенерировать метаданные, как показано выше)

enhancer.registerMetadata(jdomd);

Теперь мы можем обработать расширение, используя отдельный загрузчик классов, если требуется (например, если классы были определены динамически, например, ASM)

enhancer.setClassLoader(myClassLoader);

Наконец, мы выбираем, что нужно улучшить, и выполняем улучшение

String[] classes = {"test.Client"};
enhancer.addClasses(classes);
enhancer.enhance();

Таким образом, класс теперь расширен и готов к использованию. Вы можете просмотреть Javadocs для Enhancer API здесь .

 

API отмены запроса / тайм-аута

В некоторых случаях запрос может быть неэффективным или может страдать от проблем в базовом хранилище данных, поэтому мы не хотим влиять на приложение. В этом случае имеет смысл иметь контроль над таймаутом для запроса или иметь возможность отменить его. JDO 2.3 представляет элемент управления Query Cancel / Timeout , используя следующие новые методы для javax.jdo.Query.

void setTimeoutMillis(Integer interval);
Integer getTimeoutMillis();
void cancelAll();
void cancel(Thread thread);

Таким образом, у нас есть возможность отменить запрос по мере необходимости или просто дать ему время ожидания.

 

Контроль блокировки чтения объектов

Когда мы используем транзакции хранилища данных (пессимистичные), часто не имеет смысла просто блокировать все объекты, считанные в транзакции. По этой причине JDO 2.3 вводит контроль над тем, какие объекты заблокированы, а какие нет.

В метаданных для каждого класса вы можете указать параметр «serialize-read». Истина будет означать, что объекты этого типа будут заблокированы при чтении.

В транзакции вы можете переопределить настройки метаданных следующим способом

void setSerializeRead(Boolean serialize);
Boolean getSerializeRead();

В запросе вы можете переопределить метаданные и параметры транзакции следующим способом

void setSerializeRead(Boolean serialize);
Boolean getSerializeRead();

На этом мы завершаем наш простой обзор JDO2.3. Мы надеемся, что вам понравится его использование, и если у вас есть идеи о том, где вы бы хотели, чтобы JDO использовался в будущем, обратитесь к ним в проект Apache JDO.