Я экспериментирую с перемещением веб-приложения JDBC в JDO DataNucleus 2.1.1.
Предположим, у меня есть несколько классов, которые выглядят примерно так:
public class Position {private Integer id;частное название строки;}
открытый класс Employee {private Integer id;личное строковое имя;личная позиция;}
Содержимое таблицы Position SQL действительно не очень часто меняется.Используя JDBC, я считываю всю таблицу в память (с возможностью периодического обновления или по желанию).Затем, когда я читаю Employee в память, я просто извлекаю идентификатор позиции из таблицы Employee и использую его для получения экземпляра позиции в памяти.
Однако, используя DataNucleus, если я выполняю итерацию по всем позициям:
Extent<Position> extent =pm.getExtent(Position.class, true);
Iterator<Position> iter =extent.iterator();
while(iter.hasNext()) {
Position position =iterPosition.next();
System.out.println(position.toString());
}
А потом, с другим PersistenceManager, итерируем по всем Сотрудникам, получая их Положение:
Extent<Employee> extent =pm.getExtent(Employee.class, true);
Iterator<Employee> iter =extent.iterator();
while(iter.hasNext()) {
Employee employee =iter.next();
System.out.println(employee.getPosition());
}
Затем DataNucleus создает SQL, соединяющий две таблицы, когда я получаюПозиция сотрудника:
ВЫБЕРИТЕ A0.POSITION_ID, B0.ID, B0.TITLE ИЗ MYSCHEMA.EMPLOYEE A0 ВНЕШНИЙ ВСТУПИТЬ В МИШЕМУ.>
Насколько я понимаю, DataNucleus будет использовать кэшированный экземпляр Position, когда он будет доступен.(Это правильно?) Тем не менее, я обеспокоен тем, что объединения будут ухудшать производительность.Я еще недостаточно далеко, чтобы проводить тесты.Мои страхи неуместны?Стоит ли продолжать и эталонный тест?Есть ли способ заставить DataNucleus избегать объединения?
<jdo>
<package name="com.example.staff">
<class name="Position" identity-type="application" schema="MYSCHEMA" table="Position">
<inheritance strategy="new-table"/>
<field name="id" primary-key="true">
<column name="ID" jdbc-type="integer"/>
</field>
<field name="title">
<column name="TITLE" jdbc-type="varchar"/>
</field>
</class>
</package>
</jdo>
<jdo>
<package name="com.example.staff">
<class name="Employee" identity-type="application" schema="MYSCHEMA" table="EMPLOYEE">
<inheritance strategy="new-table"/>
<field name="id" primary-key="true">
<column name="ID" jdbc-type="integer"/>
</field>
<field name="name">
<column name="NAME" jdbc-type="varchar"/>
</field>
<field name="position" table="Position">
<column name="POSITION_ID" jdbc-type="int" />
<join column="ID" />
</field>
</class>
</package>
</jdo>
Думаю, я надеюсь, что смогу сделать так, чтобы DataNucleus продолжал и читал POSITION_ID int как часть группы извлечения по умолчанию.и посмотреть, если соответствующая позиция уже кэширована.Если это так, то установите это поле.Если нет, то сделайте объединение позже, если потребуется.А еще лучше, спрятать этот int ID где-нибудь и использовать его, если позже вызывается getPosition ().Это позволит избежать объединения во всех случаях.
Я думаю, что знания класса и значения первичного ключа было бы достаточно, чтобы избежать наивного случая, но я еще недостаточно знаю о DataNucleus.
Благодаря полученному отзыву мой .jdo теперь очищен.Однако после добавления поля POSITION_ID в группу извлечения по умолчанию я все еще получаю соединение.
SELECT 'com.example.staff.Employee' AS NUCLEUS_TYPE,A0.ID,A0."NAME",A0.POSITION_ID,B0.ID,B0.TITLE FROM MYSCHEMA.EMPLOYEE A0 LEFT OUTER JOIN MYSCHEMA."POSITION" B0 ON A0.POSITION_ID = B0.ID
Я понимаю, почему он это делает, наивный метод всегда будет работать.Я просто надеялся, что он способен на большее.Хотя DataNucleus может не читать все столбцы из результирующего набора, а скорее возвращать кэшированную Позицию, он все еще обращается к хранилищу данных для доступа ко второй таблице со всем, что влечет за собой, включая возможные операции поиска и чтения с диска.Тот факт, что он отбросит эту работу, - небольшое утешение.
То, что я надеялся сделать, это сказать DataNucleus, что все позиции будут кэшироваться, поверьте мне в этом.И если по какой-то причине вы найдете такой, которого нет, обвините меня в промахе.Я понимаю, что вам придется (прозрачно) выполнить отдельный выбор в таблице позиций.(Еще лучше, закрепите все позиции, которые вам нужно получить из-за пропуска кэша. Таким образом, вы не сможете снова пропустить кэш-память по объекту.)
Это то, что я сейчас делаю, используяJDBC, посредством DAO.Одной из причин исследования персистентного слоя было прекращение этих DAO.Трудно представить переход на слой постоянства, который не может выйти за пределы наивных извлечений, что приводит к дорогостоящим объединениям.
Как только у сотрудника есть не только должность, но и отдел, и другие поля, выборка сотрудника.вызывает доступ к полдюжине таблиц, даже если все эти объекты уже закреплены в кэше и являются адресуемыми с учетом их класса и первичного ключа.Фактически я могу реализовать это самостоятельно, изменив Employee.position на Integer, создав IntIdentity и передав его в PersistenceManager.getObjectByID ().
Я думаю, что слышу, что DataNucleus не способен на эту оптимизацию.Это правильно?Это нормально, только не то, что я ожидал.