Основы работы с базами данных

Н

Аступило время рассмотреть несколько вопросов, которые вам следует знать, прежде начать создавать простые базы данных с помощью JBuilder. Данная гла­ва объясняет, как автоматически построить приложение, которое открывает базу данных, выбирает таблицу и дает пользователю возможность просматривать и ре­дактировать данные, хранящиеся в этой таблице.

Более сложные темы, такие как отношения "главный-подчиненный" ("master- detail"), поисковые таблицы (lookups) и вычисляемые поля, будут обсуждаться в последующих двух главах. В данной главе основной акцент сделан на самых простых инструментах работы с базами данных, находящихся в арсенале JBuilder.

Однако было бы ошибкой думать, что эта глава предназначена только для начи­нающих. Некоторые фрагменты обсуждений, например, посвященные вопросу, ка­ким образом JBuilder извлекает информацию из базы данных, являются достаточно сложными.

Весь код, представленный в данной главе, JBuilder генерирует автоматически. Однако я покажу, как произвести настройку шаблонов, в соответствии с которыми происходит генерация кода. Изменяя эти шаблоны, вы можете (по крайней мере, теоретически) изменять внешний вид приложений, которые генерирует JBuilder.

Материал этой главы частично затрагивался в последних абзацах предыдущей главы. Однако теперь мы намереваемся рассмотреть этот материал более глубоко. Наша цель заключается в том, чтобы не только увидеть, что умеет делать JBuilder, но и понять, Почему он это делает. Главная программа, обсуждаемая в этой главе, входит в состав сопровождающих книгу материалов, в каталоге SimpieAuto.

Модули данных

Я намерен начать с разговора о средствах отделения кода вашей базы данных от объектов пользовательского интерфейса. В JBuilder эту полезную задачу выполняет инструмент под названием модуля данных (data module).

Строго говоря, модули данных не так уж необходимы. Вы можете, если это необ­ходимо, разместить объекты соединения с базами данных, такие как QueryDataSet или Database, непосредственно в JFrame, JPanel или JDialog. Однако я советую вам не увлекаться подобной практикой, так как при этом происходит смешение кода пользовательского интерфейса и кода базы данных. Вместо того чтобы вносить такую путаницу, я рекомендую помещать код для своей базы данных в отдельный класс, называемый модулем данных. Вам, конечно же, часто придется помещать КОМ тонет Л управления данными, такие как JdbTextField, в JFrame или JPanel.

Создание модуля данных

Давайте посмотрим, какие шаги необходимы для создания модуля данных. Для начала создайте новый проект, но на этот раз я попрошу вас не помещать в него приложение Вместо этого, мы сначала подготовим модуль данных, а затем заставим JBuilder автоматически создать приложение на основании этого модуля данных.

примечаниеБольшая часть той работы, которую я намереваюсь вам показать в пос­ледующих нескольких главах, не будет основываться на автоматически генерируемых приложениях. Но даже если вы будете использовать их в качестве начального этапа для своего проекта, вы найдете, что генерируемый код хорошо написан и прост для расшире­ния. Как я и упоминал ранее, в JBuiIder нет "черных ящиков", и генерируемый им код дос­таточно просто в редактировании. В действительности, мы собираемся довольно-таки тщательно его разобрать, чтобы увидеть, чему мы можем научиться у экспертов, кото­Рые создали этот код.

Выберите в меню пункт File ∣ New, перейдите на закладку General и запустите ма­стер модулей данных Data Module. Это очень простое одношаговое диалоговое окно. Заполните его в соответствии с рис. 41.1, изменив имя класса на AIbumDataModuIe и отметив флажки Invoke Data Modeler (Вызвать Data Modeler) и Generate headers (Сге­нерировать заголовки).

На рис. 41.1 несложно заметить, что я отметил опцию вызова Data Modeler. Data Modeler помогает автоматически создавать запросы для выборки данных, представ­ленных в вашем приложении.

Вызов Data Modeler не является обязательным этапом. Однако во многих случа­ях проще всего будет воспользоваться этим мощным инструментом. В последующих главах я объясню, что нужно делать, если вы не хотите в начале работы вызывать Data Modeler. В некоторых случаях будет совершенно неправильно использовать Data Modeler. Но если вы можете его использовать, то используйте

Рис. 41.1. Простой одношаговый процесс создания модуля данных выполняется по щелчку на кнопке OK В диалоговом окне мастера Data Module Wizard

примечаниеJBuilder-инструмент Data Modeler никоим образом нельзя назвать са­мым мощным инструментом подобного рода. Некоторые средства моделирования дан­ных, выпущенные независимыми компаниями, представляют собой крупные приложения, сравнимые по масштабам и сложности с самим JBuiIder. Этот инструмент не имеет тако­го размаха, тем не менее, он полностью справляется со своей работой. У вас не должно возникать проблем с интегрированием средств моделирования данных с инструментами, Обсуждаемыми в этой и последующих нескольких главах.

После того как вы щелкнете на кнопке OK в мастере модулей данных (Data Module Wizard), вы увидите инструмент Data Modeler, как показано на рис. 4I.2 (не путайте свои модули данных со средствами моделирования данных!).

Вы, должно быть, узнаете раздел Available Columns (Доступные столбцы) диалого­вого окна Data Modeler по предыдущей главе, где мы обсуждали Database Pilot. Вы можете использовать доступные столбцы для того, чтобы выбрать и открыть ту базу данных, которую вы хотите использовать. В данном случае, я работаю с базой дан­ных Jbbook, Которая в состав сопровождающих книгу материалов. Мы уже обсужда­ли это в предыдущей главе.

примечаниеКак говорилось в предыдущей главе, я создал версии базы данных jbbook для систем Access, InterBase и MySQL. В результате, вы можете самостоятельно выбрать требуемый тип соединения. В большинстве примеров, которые я рассматриваю в этой книге, я использую MySQL. Чтобы переключиться на другую базу данных, просто Укажите соответствующий тип драйвера, как было показано в предыдущей главе.

На рис. 41.2 вы можете видеть, что я открыл базу данных Jbbook. При этом мне потребовалось ввести имя пользователя и пароль, о чем, опять-таки, речь шла в пре­дыдущей главе. Затем я выбрал таблицу album и щелкнул на кнопке Copy All (Копи­ровать все). В этом случае я гарантирую, что пользователь будет иметь доступ ко всем полям базы данных. В частности, я создал простое SQL-оператор, которое осу­ществляет выборку всех данных из таблицы album. Вы можете просмотреть и отре­дактировать SQL-оператор в Data Modeler на закладке SQL, как показано на рис. 41.3.

рис. 41.2.
инструмент data modeler с открытой базой данных, выбранной таблицей и всеми
выбранными столбцами таблицы, которые будут использоваться в запросе
file queues view database help 
asi ai ⅝ ⅜ii 
'-querteft ` — —■* — 
 
• currentquery ∙ —— - " 
columns j where j order by i oroup by 8ql j teslj
sql8tatement 
sdjcct albuh- codz,albtjh. albuh,albtjh-typesxalbuh. ioodhess,albch- hzditjhfalbuh-jutihg,
albuh.groupcodefalbuh.cddbid,albuh. sddbhahz fmm albc^ 
j~,i ~ i÷ -∙^- ’ ,⅛,r -

,c catazaodcirr f mtnciimenl'* Λ∏d ⅜∏tnp4^har∣∣cmhprojm-!∖∣∣ntit∣ed<5^rςwrrtjtlcdfiΦmod-iλva
рис. 41.3.
просмотр sql-оператора, сгенерированного data modeler

Если вы удовлетворены внешним видом своего SQL-оператора, вы можете проте­стировать его на тестовой панели Data Modeler (см. рис. 41.4). Чтобы лучше видеть данные, можно манипулировать размерами столбцов и всего диалогового окна.

На данном этапе вам следует сохранить проделанную работу. Но прежде чем это делать, убедитесь, что в пункт меню View ∣ Options ∣ Generate Entities не содержит от­метку. Теперь выберите пункт File ∣ Save из меню Data Modeler. Это сохранит вашу работу, связанную с созданием модуля данных. Единственным местом хранения ва­шей работы в Data Modeler является java файл (модуль данных), который вы создае­те. Можно считать, что "сохранение" модуля данных является шагом, который в действительности генерирует модуль данных. Вы можете генерировать модуль дан­ных снова и снова, пока не выйдете из Data Modeler. После того, как вы выйдете из Data Modeler, вы уже не сможете снова запустить Data Modeler, кроме как для созда­ния нового модуля данных. Другими словами, вы не можете загрузить существую­щий модуль данных в Data Modeler.

,f2)0at∂ ModHet — Г:IDoCiintents λ∏<1 Seφn⅞^kh IwtjbprojecHuniittedMsfcXuntitterf6UMΛod. jav⅜≈

File Queries View Database Help

рис. 41.4.
просмотр результатов тестового выполнения запроса, который был сгенерирован data modeler
currenlqueiy
columnsl where j orderby j group by sol тей j
jj..
jj
.if.
ijunderared sky 2-highway 61 revtslted
4 ∖ undocumented windcjws
5 !unauthorized windows 95 549;the truth is spoken here
7 ihydrogen jukebox 550 и 7 seconds to anywhere
9? aja
iooo4
1000?
jj execute quety j∣

Невозможность повторного вызова Data Modeler без необходимости создания нового модуля данных — не такая уж серьезная проблема, как может показаться на первый взгляд. На любом этапе разработки вы сможете использовать большую часть функций Data Modeler посредством служебных программ, встроенных в JBuilder. Например, вы можете получить доступ ко всем частям Data Modeler, позволяющим создавать запросы. Другие автоматизированные визуальные инструменты позволя­ют создавать отношения "главный-подчиненный", поисковые таблицы и т. д. в ре­дакторе JBuilder в любое время. Я объясню принципы работы с этими инструмента­ми позже в этой, а также в последующих двух главах.

Перед выходом из Data Modeler

Я уверен, что вы обратили внимание на то, что Data Modeler содержит больше функций, нежели мы обсудили. Давайте потратим немного времени на то, чтобы рассмотреть некоторые из них. Однако я не собираюсь в этой главе глубоко их ис­следовать, так как они отвлекут нас от создания простого основания из инструмен­тов для работы с базами данных, которым мы сейчас заняты.

Если вы посмотрите раздел Queries (Запросы), показанный на рис. 41.4, то на­верняка увидите узел под названием Album. Он представляет ту работу, которая к на­стоящему моменту была проделана в отношении таблицы album. Вы можете доба­вить дополнительные узлы, по одному для каждого создаваемого запроса. Вы може­те создать множество запросов по одной и более таблице. Когда все будет готово, вы получите целый набор узлов, а не один узел под названием Album.

Вы можете установить отношения между создаваемыми вами запросами. Напри­мер, вы можете создавать отношения "главный-подчиненный", которые будут изоб­ражаться графически, в упрощенном виде, в разделе Queries (Запросы) инструмента Data Modeler.

Глядя на закладки, расположенные в нижней половине Data Modeler, вы можете убедиться, что имеется возможность создавать конструкции where, order by и group by. Эти слова соответствуют запросам различного рода, которые вы можете создавать, если хотите выбрать данные из базы данных. Позже мы обсудим их более глубоко.

примечаниеНа данном этапе вы можете выбрать в меню Data Modeler пункт File ∣ Exit. Вы вер­нетесь обратно в JBuilder, причем панель проекта теперь будет показывать ваш про­стой модуль данных. Чтобы убедиться в том, что все работает должным образом, от­компилируйте свое приложение, но не запускайте его.

Одной из функций Data Modeler, которая затронута лишь "по касатель­ной", является способность создавать сущности (entities). Выберите в меню Data Modeler пункт View I Options. Отметьте флажок Generate Entities (Генерировать сущности). При таком подходе, в соотвтетствии с архитектурой EntityDataSet, ваш код будет раз­делен на интерфейс и несколько классов. Вам, однако, следует убедиться в том, что эта Опция не была включена во время выполнения данного упражнения.

Автоматическое создание приложения

Теперь давайте-ка сгенерируем приложе­ние, основанное на созданном ранее модуле данных. Как было показано в предыдущей главе, этот шаг чрезвычайно прост.

Чтобы заставить JBuilder автоматически генерировать код для вашего приложения, выберите в меню пункт File ∣ New, а затем на закладке General — пиктограмму Data Module Application (Приложение на основе модуля данных). Не нужно вносить какие — либо изменения; просто щелкните на кноп­ке OK. Будет сгенерировано полнофункцио­нальное приложение, взаимодействующее с базой данных. После запуска программа по­явится в том виде, в котором она представ­лена на рисунке 41.5.

Чтобы запустить программу, просто щелкните правой кнопкой мыши на AlbumDataModuIeTwoTierApp в панели про­екта. Выберите в появившемся контекстном тить с установками по умолчанию). На этой вильного развития событий:

F⅛j DatrMtiduIeI twolɪer

File Help

И « ► w ♦

— *z × « S I Й

codβ∣ fsavechangesalbum {new moon daughter types]
loudnessf
medium]
rating]
croupcodef
cddbid [ad0eβs0c
cddbname ∣cassandra wilson
рис. 41.5. простое приложение, взаимодействующее с базой данных, которое было автоматически сгенерировано jbuilder
меню пункт run using defaults (3aπyc- стадии возможны три варианта непра-
■ Если вы щелкнете на зеленой кнопке запуска, программа автоматически не запустится. Вместо этого появится диалоговое окно Project Properties, открытое на закладке Run. Чтобы правильно все настроить, щелкните на кнопке New в диалоговом окне Project Properties и найдите главный файл своего проекта. В данном случае, это будет исходный файл с именем AlbumDataModuIeTwoTierAppjava. Настройка главного приложения проекта более подробно описана в главе 31 и в части V.

■ Второй проблемой может стать вопрос содержимого пути классов, куда вхо­дит драйвер вашей базы данных. В частности, вы можете получить сообщение примерно следующего содержания: "The Driver: Org.Gjt.Mm.Mysql Could Not Be Loaded" ("He Удалось загрузить драйвер Org.Gjt.Mm.Mysql"). У вас эта проблема может возникнуть, а может и не возникнуть. Это зависит от того, какой драйвер вы используете, и какие библиотеки у вас установлены. Например, если файл MmMysqlVers Ion. Jar Не входит в библиотеку и, стало быть, не присутствует в пути классов, ваша программа, вероятнее всего, пра­вильно работать не будет. Во-первых, попробуйте запустить программу, а за­тем, если возникли проблемы, попытайтесь исправить их так, как говорится ниже. Чтобы решить проблему, создайте новую библиотеку в домашнем ката­логе пользователя, указывающем на JAR-файл вашего драйвера. Выберите пункт Project ∣ Project Properties J Required Libraries в меню JBuilder. Щелкните на кнопке Add и выберите New в нижней части диалогового окна Select One or

More Libraries (Выбрать одну или более библиотек). Дайте новой библиотеке имя mm-mysql или какое-то имя, соответствующее используемому драйверу. Если есть возможность, убедитесь, чтобы в поле Location было установлено значение User Home (Домашний каталог пользователя), а не Project Home (До­машний каталог проекта). Щелкните на кнопке Add и найдите JAR-файл для своего драйвера. Щелкните на кнопке OK четыре раза, чтобы закрыть все от­крытые диалоговые окна. Теперь попробуйте запустить свое приложение и посмотрите, исчезла ли ошибка. Создание этой библиотеки в домашнем ка­талоге пользователя должно гарантировать, что в последующих проектах, вза­имодействующих с базами данных, эта библиотека будет автоматически до­бавляться в раздел Required Libraries диалогового окна Project Properties. Если вам нужна более подробная информация по работе с библиотеками, просмот­рите соответствующие главы части V.

■ Третий вариант неправильного развития событий, который может иметь мес­то на этом этапе, заключается в том, что вы могли случайно щелкнуть на Generate Entities (Генерировать сущности) в Data Modeler в пункте меню View | Options. Если так оно и было, это означает, что вы создали приложение не­правильного типа. Скорее всего, самым простым способом устранить пробле­му будет начать проект с начала, если конечно вы не хотите иметь дело с сущ­ностями. Как только вы поймете суть всего происходящего, вы сможете про­ходить все описанные нами этапы буквально за несколько секунд.

Разработанная вами программа позволяет перебирать данные в наборе данных. Вы можете редактировать строки и записывать данные в набор данных.

Сохранение данных: навигационная панель

В верхней части приложения вы можете видеть компонент JdbNavTooiBar. Этот чрезвычайно важный и очень широко используемый компонент содержит несколь­ко пиктограмм. Четыре пиктограммы слева позволяют перемещаться по набору дан­ных. Следующая пиктограмма, со знаком плюс, позволяет вставлять новую строку. Пиктограмма со знаком минус дает возможность удалять строку. Следующие две пиктограммы предназначены для сохранения или отмены изменений, внесенных вами в строку. Пиктограмма с изображением двойных кавычек позволяет сделать ко­пию текущей строки.

Все эти изменения применяются только к копии данных, которая имеется в на­боре данных на локальной машине. Чтобы в действительности передать изменения на сервер, выберите в навигационной панели предпоследнюю пиктограмму. Чтобы обновить свои данные данными с сервера, щелкните на последней пиктограмме в навигационной панели. При этом произойдет перезапись всех несохраненных дан­ных. Если вы не будете пользоваться предпоследней пиктограммой ("сохранить из­менения"), то сможете работать только лишь с локальной копией данных, не сохра­няя работу на сервере.

В данном примере я попытался показать простейшую из возможных автомати­чески сгенерированных программ. Однако вы можете заставить JBuilder создавать более сложные программы, что демонстрируется в следующей главе

Одноэлементный способ создания модуля данных

Теперь пришло время заняться исследованиями созданного кода. Вы можете просмотреть полный исходный код модуля данных в листинге 41.1. В сопровождаю­щих книгу материалах данную программу можно найти под названием SimpleAuto.

Листинг 41.1. Исходный код простого потомка класса DataModuIe, созданный с помощью Data Modeler package untitled6;

Import java. awt∙*;

Import java. awt. event.*;

Import com. borland. dx. dataset.*;

Import com. borland. dx. sql. dataset. *;

Public class DataModulel implements DataModule

{

Private static DataModulel myDM;

Database databasel = new Database();

QueryDataSet album = new QueryDataSet(); public static DataModulel getDataModule()

1

If (myDM == null)

{

MyDM = new DataModulel () ;

}

Return myDM;

}

Public DataModulelO {

Try

1

Jbɪnit () ;

}

Catch(Exception e)

<

E. printStackTrace();

1

1

Private void jbɪnit() throws Exception {

Album. SetQuery(

New QueryDescriptor(databasel,

"SELECT ALBUM. CODE, ALBUM. ALBUM, ALBUM. TYPES,"+

"ALBUM. LOUDNESS, ALBUM. MEDIUM, ALBUM. RATING, n +

"album. Groupcode , album. cddbid,,, +

"album. Cddbname from album", Null, true, Load. ALL));

Databasel. SetConnection( new ConnectionDescriptor(

"jdbc:mysql://bree/jbbook",

"root",

"foo", false,

"org. gjt. mm. mysql. Driyer"));

)

Public Database getDatabasel() (

Return databasel;

}

Public QueryDataSet getAlbum() <

Return album;

}

Первое, что несложно было заметить в этом коде, — это то, что в нем реализована модифицированная версия одноэлементного шаблона:

Private static DataModulel myDM;

// Одноэлементный шаблон

Public static DataModulel getDataModule()

{

If (myDM ≈ null)

{

MyDM = new DataModulel () ;

}

Return myDM;

}

∕∕ Конструктор Public DataModulelO {

Try

{

Jblnit () ;

}

Catch(Exception e)

{

E. printStackTrace () ;

)

)

Одноэлементный шаблон разработан с целью гарантии того, что будет создан только один экземпляр объекта. Открытие базы данных является дорогостоящим с точки зрения времени и памяти. В результате, вы не должны иметь слишком много копий этого элемента в памяти. Чтобы привести в действие это правило, предлага­ется вызывать метод GetDataModule Вместо того, чтобы получать прямой доступ к конструктору:

AlbumDataModule AlbumDataModule =

примечаниеUntitled6.AlbumDataModule. getDataModule();

Как вы увидите далее в этой книге, в JBuiIder существует мастер, назы­вающийся Use DataModuIe Wizard (Мастер использования базы данных). Он автомати­чески вызывает либо этот метод, либо конструктор, по вашему желанию. Если сомневае­тесь, я рекомендую вызывать метод getDataModule. В мастере это называется "Sharinc∣ the static instance of the data module" ("Совместное использование статичес­кого экземпляра модуля данных").

Для того чтобы действительно заставить работать одноэлементный шаблон, кон­структор необходимо объявить приватным:

Private DataModulelO

{

Try

{

Jblnit();

}

Catch(Exception Е)

{

Е. printStackTrace();

}

}

примечаниеЕсли конструктор является приватным, невозможно создать этот объект по-дру­гому, кроме как вызвав метод getDataModule. Это гарантирует, что будет существо­вать только одна копия модуля данных. В результате я предлагаю вам проделывать это с вашими приложениями и изменять сигнатуру конструктора в модуле данных на private. Если вы хотите получить доступ к объекту, обратитесь к методу getDataModule.

В действительности, могут возникнуть вполне логичные причины, почему вам следовало бы располагать двумя копиями модуля данных в памяти. Если вы знаете, что делаете, конечно же, вы можете так поступать. Однако по умолчанию я рекомендую орга­низовать совместное использование единственного экземпляра модуля данных.

Открытие базы данных

Безусловно, создание модуля данных представляет собой лишь отдельную деталь реализации. Для нас имеют значение только сами данные.

JBuiIder вставляет в метод jbinit код открытия таблицы:

Database databasel = new Database();

QueryDataSet album = new QueryDataSetO ;

Private void jblnit() throws Exception {

Databasel. SetConnection(new ConnectionDescriptor(

,, jdbc:mysql: //bree/jbbook" ,

"root”,

,’foo" , false,

,, org. gj t. mm. my sql. Driver)) ;

Album. setQuery(new QueryDescriptor(databasel,

" SELECT ALBUM. CODE, ALBUM. ALBUM, ALBUM. TYPES, "+

"ALBUM. LOUDNESS, ALBUM. MEDIUM, ALBUM. RATING,π +

"album. Groupcode, album. cddbid, ∙, +

"album. Cddbname from album", null, true, Load. ALL));

Чтобы подключиться к своей базе данных, вызовите метод Databasel. SetConnection. Для выполнения вызова сначала потребуется создать объект ConnectionDescriptor. Этот объект выглядит сложным, потому что он име­ет длинное имя и в сгенерированном коде указан полный путь к содержащему его пакету:

Com. borland. dx. sql. dataset. ConnectionDescriptor

Однако на самом деле ConnectionDescriptor Представляет собой очень простой класс. Он только лишь обеспечивает упаковку требуемых данных для того, чтобы со­здать соединение с базой данных JDBC. Здесь, например, показан один из наибо­лее часто используемых конструкторов объекта:

Public ConnectionDescriptor(String ConneetionURLz String UserNamez String password, boolean promptPasswordz

String driver)

This. ConneetionURL

= ConneetionURL;

This. userName

= userName;

This. password

= password;

This. promptPassword

= promptPassword

This. driver

= driver;

}

примечаниеОн, кроме того, представляет собой один из наиболее сложных методов в объек­те ConnectionDescriptor! Чтобы создать соединение, JDBC должен знать URL со­единения, имя пользователя, пароль и драйвер. ConnectionDescriptor Представля­ет собой простой объект, предназначенный для того, чтобы дать JBuilder возмож­ность отслеживать упомянутую информацию.

В DataExpress код создается на основе JDBC. В действительности, дан­ные ConnectionDescriptor только лишь передаются стандартным JDBC-командам, ко­торые, собственно, и выполняют основную работу по подключению к базе данных. Мы немного поговорим об использовании JDBC в последующих главах. В каталоге JdbcTests в сопровождающих материалах вы сможете найти примеры программ, все­цело использующих JDBC. Вам нужно будет заняться редактированием этих простых про­грамм, чтобы они указывали на базы данных и драйверы, загруженные в вашей системе или сети.

Наиболее важным фрагментом передаваемой вами информации является ConneetionURL

"Jdbc:Mysql://Bree/Jbbook"

Фрагмент "jdbc" в этой строке говорит, что мы хотим использовать инструменты интерфейса JDBC, встроенные в виртуальную машину Java (JVM). Фрагмент "Mysql" В этом выражении указывает на то, что для подключения к базе данных не­обходимо использовать mysql-драйвер. JDBC использует эту строку для того, чтобы найти имя класса того драйвера, который вы хотите использовать. В данном случае, ЭТС Org. 4J T. Mm. Mysql. Driver.

примечание"Ьхее" — Это имя машины, на которой хранится база данных В большинстве случаев вам придется изменить это имя на Iocaihost или на имя другого сервера вашей системы, jbbook представляет собой имя базы данных MySQL, к которой эта программа получит доступ.

В коде, входящем в состав сопровождающих книгу материалов, я при­ложил все усилия для того, чтобы изменить все ссылки на Ьхее или другие серверы в своей системе на Iocalhost. Однако существует вероятность, что какие-то ссылки я пропустил. Если у вас при пользовании программами возникли проблемы, проверьте данный фрагмент кода, чтобы убедиться, что проблемы возникли не по этой причине. Также проверьте имя пользователя и пароль.

Переносимость JDBC подразумевает, что теоретически вы можете сменить базу данных, к которой нужно получить доступ, простым изменением одного слова этой строки:

"Jdbe:Interbase://Bree/Jbbook"

примечаниеЗдесь я изменил "Mysql" На ,,Interbase". Если вы тоже измените строку драйве­ра в последнем параметре, данный URL соединения будет использовать систему InterBase, а не MySQL. Если у вас на обоих серверах хранятся такие же данные, ос­тавшаяся часть приложения может, по крайней мере, теоретически, оставаться та­кой же. В выполненных мною тестах я смог успешно делать такого рода замены. Од­нако в некоторых случаях вам может понадобиться вставить в свою программу такие SQL-операторы, которые работают на одном типе серверов баз данных, и не работа­ют на другом.

Конечно же, вряд ли у вас будет одинаковый набор таблиц с одинако­выми метаданными на двух серверах различного типа. Но если вы захотите сделать та­кое, то это возможно, по крайней мере, теоретически. Мой случай уникален, поскольку сопровождающие книгу материалы включают в себя базы данных для систем MySQL, Access и InterBase. Я решил отказаться от создания одинаковых баз данных на множе­стве серверов. В этом мне помогли программы, с которыми вы можете ознакомиться в Сопровождающих материалах (их названия MusicConvext и ConvextAddxess).

Следующие несколько полей строки соединения понять гораздо проще:

"XOOt",

"Foo", False,

,,Oxg.Gjt .Xmn.Mysql.Dxivex")) ;

"Xoot" Это имя пользователя или того, кто подключился к базе данных, "Foo" — недоступный пароль пользователя Булево значение False Указывает на то, что пароль запрашивать не следует. Если вы поставите здесь Txue, При первом запуске приложение запросит имя пользователя и пароль. Пожалуйста, запомните это. Вам не следует писать код, запрашивающий имя пользователя и пароль у пользователя. Эта функция встроена в инструменты по работе с базами данных ком­пании Borland.

примечаниеМне, возможно, следует уточнить то, что я сказал в последнем абзаце. Некоторые пользователи могут найти диалоговое окно, разработанное Borland, не впол­не дружественным по отношению к пользователю. Если онО не соответствует вашим Запросам, вы должны разработать собственный код.

Последняя строка представляет собой имя драйвера, который может использо­вать JDBC для обращения к базе данных. Мы говорили о драйверах более глубоко в предыдущей главе.

Как только вы завершите этот этап, используемый вами объект Database Станет полностью инициализированным. Вам нужно будет воспользоваться этим объектом для того, чтобы получить доступ к таблицам своей базы данных. Объект Database Представляет собой соединение с действительными данными вашей базы данных в системах MySQL, InterBase, Oracle, MSSQL, JDataStore или Access.

QueryDataSet и организация запросов к базе данных

Метод jbinɪt, который мы изучаем, кроме того, содержит и вызов, определяю­щий сам SQL-запрос.

Album. SetQuery(

New com. borɪand. dx. sql. dataset. QueryDescriptor(databasel,

" SELECT ALBUM. CODE, ALBUM. ALBUM, ALBUM. TYPES, ALBUM. LOUDNESS,,, +

"ALBUM. MEDIUM, ALBUM. RATING, ALBUM. GROUPCODE, ALBUM. CDDBID," +

"album. Cddbname from album" , null, true, Load. ALL));

Переменная Album Имеет тип QueryDataSet. QueryDataSetЭто фундаменталь­ный компонент в мире баз данных JBuilder. Вы еще не раз будете пользоваться этим компонентом.

Компонент QueryDataSet Весьма прост для понимания. Этот инструмент ис­пользуется для извлечения данных из базы данных. Вы также можете применять его в целях получения доступа к инструментам сохранения и обновления данных.

SQL-операторы в QueryDataSet Предназначены только для извлечения данных. Когда вам нужно будет обновить, удалить или вставить строки в таблицу, используй­те вместо них методы QueryDataSet. Я попрошу вас на секунду сфокусироваться на этой мысли, поскольку это очень важно. Для извлечения данных из набора данных пользуйтесь SQL-операторами, но для обновления, удаления или вставки строк дан­ных применяйте методы. Убедитесь, что вы поняли то, что я сказал, прежде чем мы двинемся дальше. Позже в этой главе я, конечно же, объясню, как удалять и обнов­лять данные.

примечаниеВо многих других средах разработки баз данных вам нужно было бы использовать язык SQL и для запросов, и для вставки, и для удаления, и для обновления данных. В действительности, JBuiIder тоже использует SQL для выполнения этих задач. Но частично работа QueryDataSet и связанного с ним класса с именем resolver заключа­ется как раз в том, чтобы скрыть сложность обновления набора данных. Вместо того что­бы составлять SQL-операторы, вы даете простые команды, такие как album. setstring или album. saveChanges. Все это более глубоко мы обсудим немного позже. В част­ности, обратитесь к разделу "Мониторинг SQL-активности" в конце главы. В этом разде­ле объясняется, как можно просматривать SQL-операторы, которые автоматически гене­Рирует JBuIder.

В большинстве случаев QueryDataSet Создается путем помещения компонента в модуль данных. Если нужно, то разумеется, вы можете создать упомянутый объект в коде. Для того чтобы создать QueryDataSet, Потребуется добавить в код следующую простую строку:

QueryDataSet Album = New QueryDataSetO ;

Как будет показано далее, вы можете открывать QueryDataSet И выводить его со­держимое в таблице с использованием всего двух вызовов:

JdbTable JdbTablel = new JdbTable();

JdbTablel. SetDataSet(AlbumDataModulel. getAlbum());

Короче говоря, с помощью JBuilder можно очень легко показать пользователю актуальные редактируемые данные. Затем можно воспользоваться JdbNavToolBar, Чтобы давать такие команды, как Refresh, Post Или Save. Наличие инструментов подобного рода и является причиной, по которой вам лучше было бы использовать встроенные в JBuilder инструменты по работе с базами данных, а не простой JDBC — код. JDBC весьма и весьма элегантен, однако он не настолько мощный, как пока­занные здесь инструменты.

Единственную сложность в данном процессе представляет организация запросов к данным. Как вы видели, Data Modeler генерирует этот запрос автоматически. Од­нако для того чтобы понять запрос, следует тщательно его изучить.

Как вы помните, нашей переменной типа QueryDataSet С именем Album Присво­ен дескриптор запроса QueryDescriptor. Конструктор QueryDescriptor Выглядит следующим образом:

Public QueryDescriptor(Database Database,

String Query,

ReadWriteRow parameters, boolean executeθnθpen, int IoadOption)

Первые два параметра могут быть не совсем понятными. Первый параметр — это используемый вами объект Database, А второй — созданный вами запрос. Мы будем использовать ReadWriteRow В главе 43, когда начнем обсуждать параметризованные запросы. Параметризованные запросы можно использовать для того, чтобы легко и просто модифицировать запрос непосредственно перед его передачей. Например, они позволят вам во время выполнения программы указать, что нужно выбрать из базы данных все строки, для которых в поле Artist Содержится определенное зна­чение, например "Vivaldi" ИЛИ "Bartok".

Параметр Executeθnθpen, Возможно, является самым полезным, если вы не хо­тите извлекать набор данных автоматически на стадии конструирования по причи­не его слишком большого размера, либо потому, что соединение работает чересчур медленно. Установите для этого параметра значение False, И вы сможете редакти­ровать свои визуальные компоненты в JBuilder без извлечения набора данных из сервера. Обычно это не является необходимым, но если вам это понадобится, знай­те, что такой вариант существует. Конечно же, могут возникнуть и другие причины, по которым вам нужно было бы задать для этого параметра значение False. В об­щем, его наличие обеспечивает некоторую гибкость.

До этого момента все было довольно-таки просто. Последнее поле, называющее­ся IoadOption, может оказаться более трудным для понимания. Его основное пред­назначение заключается в том, чтобы определять способ извлечения запрошенных вами данных из набора данных. Эта тема может быть сложной. Я планирую посвя­тить ей отдельный раздел.

Как JBuiIder извлекает данные

Параметр IoadOption Класса QueryDescriptor Может принимать следующие значения:

Public interface Load

Public static final int ALL = O;

Public static final int ASYNCHRONOUS = 1 ; public static final int AS_NEEDED — 2; Public static final int UNCACHED = 4;

}

Я рекомендую устанавливать для него значение Load. all, пока вы поближе не познакомитесь с DataExpress Хотя другие варианты вполне могут оказаться полез­ными, однако если вы не проявите определенную осторожность, они повлекут за со­бой проблемы.

Далее дан краткий обзор доступных вам вариантов:

■ all. Используйте этот вариант для того, чтобы извлечь из набора данных все строки. Как говорилось в предыдущей главе, подобная команда может выб­рать буквально мегабайты данных. Для того чтобы ограничить количество ви­димых записей, вы можете установить в качестве значения свойства MaχRows Класса QueryDataSet Некоторое осмысленное число, например 500. Еще даже лучшим вариантом будет изменить свой запрос таким образом, чтобы он воз­вращал набор данных меньших размеров. В конце концов, зачем пользовате­лю могут понадобиться 10 000 записей? По умолчанию, для MaχRows Установ­лено значение -1, которое означает, что DataExpress попытается извлечь все доступные строки.

■ asynchronous. Используйте этот вариант, чтобы запустить запрос в отдель­ном потоке. Это необходимо делать, если выполнение запроса занимает мно­го времени, что приводит к зависанию вашего приложения. Если ваше при­ложение по настоящему зависнет, это средство не поможет. Главная идея зак­лючается в том, что если извлечение набора данных займет изрядное время, у пользователей все равно будет возможность получить доступ к меню вашего приложения, даже во время извлечения набора данных. В документации по JBuilder сказано, что этот вариант при определенных обстоятельствах может привести к коллизии, связанной с потоком. Вы можете обратиться к методу QueryDataset-CioseProvider, Чтобы заставить операцию завершить работу, прежде чем что-нибудь произойдет. При этом осуществиться смена значения параметра с asynchronous на all. Вам может понадобиться принудительно завершить выполнение, если вы хотите произвести операцию для всех запро­шенных вами строк.

850

■ as_needed. Этот вариант также может радикально улучшить производитель­ность разрабатываемого приложения. Здесь главная идея состоит в том, что в каждый отдельный момент времени вы на сетке будете видеть только один эк­ран, полностью заполненный данными. Если вы переместитесь вниз в преде­лах сетки, то с сервера будут переданы новые данные. Для того чтобы нала­Дить КОЛИЧеСТВО ВЫВОДИМЫХ СТРОК, МОЖНО ВОСПОЛЬЗОВатЬСЯ MaxRows И MaχDes±gnRo⅞rs. Если вы выберите as_needed, значение maxRows по умолча­нию будет равно 25, а не бесконечности, как обычно.

■ uncached. Этот вариант весьма похож на as_needed, но вместо того, чтобы за раз извлекать данные в соответствии с размером экрана (25 строк), он за один раз извлекает только одну запись. Часто одну запись можно извлечь с сервера практически мгновенно. В результате этот вариант может принести пользу, если у вас отсутствует хорошее соединение с сервером. Не стоит и говорить, что при работе с данным вариантом для вывода данных лучше всего сеткой не пользоваться

Существует несколько способов исследовать поле IoadOption. Этим мы и зай­мемся в следующем разделе.

Мониторинг SQL-активности

Один ИЗ способов приступить К изучению принципов работы ПОЛЯ IoadOption Со­стоит В ТОМ, Чтобы поместить В НИЖНЮЮ Часть формы компонент JdbStatusLabel, а затем сослаться на него в своем наборе данных:

JdbStatusLabell. SetDataSet (SiyDataSet)

В элементарном приложении, которое мы только что завершили, это было сде­лано автоматически. Эта подпись может помочь вам отследить, сколько именно строк вашего запроса было возвращено сервером.

Чтобы больше узнать по поводу IoadOption, установите для него значение Load.AS_NEEDED:

Album. SetQuery(

New com. borland. dx. sql. dataset. QueryDescriptor(databasel,

"SELECT ALBUM. CODE, ALBUM. ALBUM, ALBUM. TYPES, ALBUM. LOUDNESS,’, +

"ALBUM. MEDIUM, ALBUM. RATING, ALBUM. GROUPCODE, ALBUM. CDDBID,» +

"ALBUM. CDDBNAME FROM ALBUM", null, true, Load. AS_NEEDED));

При первом запуске своей программа, вы, глядя на JdStatusLabel, Наверняка заметите, что вместо нескольких сотен строк данных было загружено всего лишь 25 строк набора данных. Затем, по мере того как вы будете прокручивать таблицу вниз, вы сможете увидеть на надписи состояния, когда загружаются дополнительные строки

Однако существуют лучшие способы узнать даже больше о том, что происходит. Один из них заключается в том, чтобы использовать в своем приложении кнопку JDBC Monitor. Чтобы это сделать, сначала выберите в меню пункт Project ∣ Project Properties, перейдите на закладку Required Libraries и добавьте в список библиотек JBCL. Закройте диалоговое окно, выберите Bean Chooser и найдите следующий

примечаниеКласс: com. borland. jbcl. sql. monitor. MonitorButton. Поместите кнопку на форму, напри­мер в нижнюю часть AIbumUIBean. Запустите свою программу, после чего щелкните на кнопке, чтобы просмотреть выходные данные.

Я знаю по собственному опыту, что не все драйверы будут с готовнос­тью выводить данные в JDBC Monitor или в файловые потоки DriveManager, о которых мы поговорим немного позже. Например, у меня возникают проблемы с драйверами JDBC, тогда как драйверы ODBC для систем Access или InterBase работают превосходно. Даже если вы хотите, чтобы ваша программа в конечном итоге использовала драйвер JDBC для InterBase или MySQL, стоит попытаться отлаживать ее с применением драйверов ODBC. К счастью, как описывалось в разделе "Открытие базы данных", переключение Между драйверами осуществляется легко и просто.

Если вы не хотите использовать кнопку MonitorButton, Вы можете вставить ка­кой-нибудь из представленных ниже выражений, прежде чем делать что-либо в сво­ем модуле данных:

Java. sql. DriverManager. SetLogStream(System. out);

Java. sql. DriverManager. SetLogWriter(new java. io. PrintWriter(System. out));

Первое выражение предназначено для использования с JDBC 1.0, а второе — для JDBC 2.0. Первое выражение должно работать в любом случае. Их хорошо было бы поместить в конструкторе модуля данных до вызова метода jbinit.

Если все работает хорошо, при вызове SetLogStream и установке для IoadOptions значения all в окне сообщений JBuilder должно появиться огромное количество данных. При выборе значения as_needed будет выводиться относитель­но небольшое количество данных. По мере того, как вы будете прокручивать набор данных, когда будет появляться новый набор из 25 строк, вы увидите в окне сообще­ний очередную порцию данных. Если вы выберете значение uncached, то увидите, что будет появляться одна запись за раз, при каждом щелчке на кнопке Next в пане­ли навигации.

Для значения uncached вывод одной строки данных при использовании SetLogStream может выглядеть следующим образом:

Get integer data (SQLGetData), hStmt=189276352, column=l

Value=4

Get string data (SQLGetData), hStmt=189276352, column=2, maxLen=46 Undocumented Windows

Get integer data (SQLGetData), ħStmt=189276352, column=3

Value=1000

Get integer data (SQLGetData), hStmt=189276352, column=4

NULL

get integer data value=1000 get integer data value=7
get integer data value=3
get string data get string data
(sqlgetdata)
(sqlgetdata)
(sqlgetdata)
(sqlgetdata), (sqlgetdata),
, column=5
, column=6
, column=7
column=8, column=9,
, hStmt=189276352

, hStmt=189276352

, hStmt=189276352

maxlen=21 ma×len=41HStmt=189276352,

HStmt=189276352,

Здесь ключевым является поле column (столбец), за которым следует значение, хранящееся в этом поле. Например, столбец 2 с максимальной длиной 46 содержит Значение "Undocumented Windows".

Если вы щелкнете на кнопке Next в панели навигации, то увидите, как появится еще одна запись такого же размера. Это и есть последовательно наращиваемая ско­рость обработки транзакций, которая и делает программу настолько чувствительной в плане откликов на пользовательские команды.

Другая альтернатива заключается в том, чтобы установить для IoadOption значе­ние asynchronous. Если вы прослеживаете SQL-активность с помощью SetLogstream, то, вероятно, вы увидите, что ваш интерфейс пользователя возника­ет на экране, тогда как данные на панели сообщений все еще прокручиваются. Пау­зы, которая возникает в работе SetLogstream, достаточно для того, чтобы опция asynchronous оказалась действительно полезной в данном приложении.

примечаниеВы можете видеть, что работают два потока. Один занят загрузкой данных и вы­дачей данных в окно сообщений. Другой поток выводит начальные порции данных по мере их доступности. Интерфейс пользователя активен, и пользователь может просматривать доступные данные даже в тогда, когда их прием из сервера еще не за­вершен.

Uιea∣∣∣∣^∣Biaι in в главе 42 мы рассмотрим компонент DBEventMonitor. Этот компо­нент может помочь в исследовании событий в коде JBuiIder DataExpress. Его функцио­нальные возможности отличаются от методов мониторинга, представленных в этой главе, поскольку он основан на инструментах Borland, а не на JDBC-коде. Тем не менее, он все же является еще одним инструментом, предназначенным для просмотра кода базы дан­Ных и получения отчетов по поводу того, что именно происходит.

Если вы находите все описанное выше не особенно понятным, не переживайте. Не настолько важно, чтобы вы, как новичок, полностью все понимали. В большин­стве случаев ваши базы данных будут достаточно малы, чтобы можно было работать с установленным по умолчанию значением IoadOptions. all. Однако если вы нач­нете работать с наборами данных больших размеров, или если связь с базой данных будет медленной, то очень даже неплохо будет знать об этих альтернативных значе­ниях.

Методы доступа к модулю данных

Как вы помните, мы все еще находимся в процессе изучения автоматически сге­нерированного кода для вашего модуля данных. Мы просматриваем строку за стро­кой, поскольку этот код предельно важен.

Последние строки кода выглядят так:

Public Database getDatabasel()

{

Return databasel;

}

Public QueryDataSet getAlbum()

{

Return album;

}

Назначение этого кода довольно-таки ясно: он предоставляет доступ к двум глав­ным объектам класса. Возможно, вы не будете удивлены, узнав, что я считаю, что хорошей идеей было бы удалить этот код. Модуль данных должен быть независи­мым. Эти методы экспортируют внутреннюю структуру модуля данных и дают дру­гим классам возможность взаимодействовать с ними. В большинстве случаев это плохо влияет на общее состояние проекта.

Изучение сгенерированного приложения

Мы подробно рассмотрели модуль данных. На самом деле нет необходимости настолько детально исследовать приложение, генерируемое JBuilder. Однако не­сколько слов об этом коде все же следует сказать.

Давайте посмотрим, какие файлы генерирует JBuilder:

Главный пакет:

AlbuinDataModuleTwoTierApp. java

AlbuinDataModule. ɔava

Пакет пользовательского интерфейса:

AlbumUIBean. java

ClientAboutBoxDialog. java

ClientFrame. java

ClientResources. java

Разбивка этого приложения является достаточно логичной. Один набор файлов (оба к визуальному интерфейсу дела не имеют) хранится в главном пакете. Весь код, имеющий отношение к интерфейсу, хранится в отдельном пакете. Опять-таки, этот способ разделения приложения на части является правильным. Имеющий глаза, да увидит, имеющий уши да услышит’

Файлы AlbumDataModuleTwoTierApp. java И ClientFrame. java Более или менее идентичны первым двум файлам, генерируемым при создании любого другого JBuilder-приложения. Другими словами, они представляют собой лишь небольшую разновидность стандартных файлов Applicationl. java И Framel. java, Которые ге­нерирует мастер приложений. Файл CiientAboutBoxDiaiog. java Также похож на то, что обычно производит мастер приложений JBuiIder. Очевидно, что его рассмот­рение не представляет особого интереса в данном контексте.

Таким образом, у нас остается только два файла: CiientResources И AlbumUiBean. Файл ресурсов клиента не вполне соответствует теме данной главы, но я нахожу его интересным, поэтому мы рассмотрим его позже в этой главе. Здесь же мы сфокусируем основное внимание на файле AlbumUiBean. java, Который не явля­ется ни особо сложным, ни хоть в чем-го удивительным фрагментом кода.

Я не стану воспроизводить здесь целиком весь AibumUiBean. В целом, он пред­ставляет собой всего лишь набор компонентов JLabel и JdbTextFields, располо­женных на небольшой панели JPanel, которая использует GridLayout и потому вставлена в JPanei большего размера с применением компоновки GridBagLayOut:

JdbTextField fieldCODE;

IabelCODE. setText("Code");

FIeldCODE. SetColumnNanie ("CODE”) ; fieIdCODE. SetDataSet(dataSet); panelCODE. setLayout(gridLayoutl);

IabelCODE. SetHorizontalAlignment(SwingConstants. RIGHT); panelCODE. add (IabelCODE); panelCODE. add(fieIdCODE); this. add(panelCODE,

New GridBagConstraints (1, 2, 2, 1, 1.0, 1.0,

GridBagConstraints. NORTH, GridBagConstraints. HORIZONTAL, new Insets (3, O, 3, 3), O, O)) ;

FieldC0DE является компонентом типа JdbTextField. Он представляет собой визуальный компонент, созданный компанией Borland с целью вывода единствен­ного поля таблицы. Вам нужно лишь сказать JdbTextField, с каким набором дан­ных он должен быть связан, и какое поле набора данных необходимо вывести:

FIeldCODE. SetColumnName("CODE"); fieIdCODE. SetDataSet(dataSet);

После того, как вы это сделаете, fieldC0DE будет работать как обычный JTextField, с той лишь разницей, что он будет содержать поле вашего набора дан­ных. Если вы щелкните на пиктограмме Save навигационной панели, то внесенные в этом поле изменения будут сохранены в наборе данных, если только они не будут нарушать правила целостности базы данных.

Остальная часть кода этого класса просто располагает панель и текстовое поле рядом друг с другом, а затем вставляет панель в изображение большего размера, ко­торое содержит элементы управления, предназначенные для вывода всего набора полей базы данных.

Генерация кода и шаблоны

Код, генерируемый JBuilder, не является жестко запрограммированным в JBuilder. Наоборот, существует система, позволяющая изменять код, генерируемый JBuilder.

Код, который был сгенерирован в AibumuiBean, взят из ресурсов, хранящихся в каталоге шаблонов, который находится где-то вне корневого каталога JBuilder. На­пример, ВЫ Можете Обнаружить его В каталогах C:\JBuilder\templates или в /home/user-name/jbuilder/templates.

Шаблоны (templates) выглядят не особенно красиво. Тем не менее, они содержат фрагменты кода, из которых создаются приложения.

В данном случае вам следует взглянуть на текстовый файл ColumnarUIBean. java, template, находящийся В каталоге JBuilder/templates. Найдите строку кода, которая похожа на следующую:

This. add(panel[MakeProperCase(this)],
new java. awt. GridBagConstraints(1,

[IncrementNumericHintClNumericHint")], 2, 1, 1.0, 1.0, java. awt. GridBagConstraints. NORTH, java. awt. GridBagConstraints. HORIZONTAL, new Insets(3, O, 3, 3), O, O)) ;

Большая часть кода, показанного здесь, попала в AibumuiBean В неизмененном виде. Необычно выглядящие части кода, такие как IncrementNximericHint, Пред­ставляют собой макросы, написанные на языке шаблонов JBuilder Вы сможете най­ти некоторые из этих макросов в файле Macros. template В каталоге шаблонов:

[MACRO IncrementNumericHint]

[IF TYPE == "StringObject"]

[FOR get (VALUE) ]

[put(StringObject. VALUE, 1 + VALUE)]

[RETURN 1 + VALUE]

[END]

[ENDIF]

[RETURN 0]

[END]

Если необходимо внести изменения в код, который порождает JBuilder, потребу­ется отредактировать код этих шаблонов Например, если вы измените фрагмент New Insets (3, O, 3, 3) на new Insets (5, O, 5, 5), КОД GridBag, Производимый JBuilder, будет вместо троек содержать пятерки.

Хотите ли вы редактировать эти шаблоны или нет, решать вам. Откровенно гово­ря, я не нахожу код шаблонов очень вдохновляющим. Однако если вы хотите внести какие-либо изменения, вот файлы, можете делать с ними все, что вам угодно.

CIientResource

Остался один последний файл, на который вам следует хотя бы взглянуть при исследовании кода, который для вашего проекта сгенерировал JBuilder. Файл ClientResources. Java ВКЛЮЧает В себя ClientResourceBundle, Который содержит все строки, используемые в приложении. Его исходный код приведен в листинге 41.3.

Листинг 41.3. Файл ClientResourcesjava содержит строки, используемые в приложении

Package untitled8._AlbumDataModule. twotier;

Import java. text. MessageFormat;

static final object[][] contents =
{ "file”,
{ "fileshortcut",
{ "exit",
{ "exitshortcut'',
{ "actions",
( "actionsshortcut",
{ "removetab",
{ "removetabshortcut { "help",
{ "helpshortcut",
{ "about",
{ ''aboutshortcut",
{ "version",
{ "copyright",
"file" ),
"f" },
"exit" },
"x" ),
"actions " ) ,
"a" },
"remove tab" ),
, "r" ),
"help" ),
"h" },
"about" ),
"a" },
"version 1.0" },
"copyright (c)" },

Public class ClientResources extends java. util. ListResourceBundle {

{ "comments”, { "ok",
{ "refresh",
{ "save",
{ "saveall",
{ "result",
public object[][]
(
"JBuilder Generated Application" "OK" },

"Refresh" },

"Save" },

"Save All" },

"result" },

GetContents()

),Return contents;

}

Public static String format(String pattern, Object pi)

{

Return MessageFormat. format(pattern, new Object[] {pl});

}

Public static String format(String pattern, Object pi, Object p2)

{

Return MessageFormat. format(pattern, new Object[] {pl, p2}) ;

)

Public static String format(String pattern, Object pi, Object p2, Object ρ3)

{

Return MessageFormat. format (pattern, new Object [] {pl, p2, p3}) ;

1

Public static String format(String pattern, Object[] objects)

{

Return MessageFormat. format(pattern, objects);

)

B этом файле строки организованы парами. Первый элемент пары представляет собой имя строкового ресурса, а второй элемент — сам ресурс. Я бы использовал этот файл следующим образом:

Java. util. ResourceBundle res =

GetBundle("untitled8._AlbumDataModule. twotier. ClientResources"); RoenuHelp. SetText(res. getString("Help"));

RoenuHelp. SetMnemonic(res. getString("HelpShortcut").CharAt(O),; menuHelpAbout. setText(res. getString("About"));

MenuHelpAbout. SetMnemonic(res. getString("AboutShortcut").charAt(O));

Как видите, все строки для меню приложения берутся из этого ресурса.

Эта система красива вдвойне:

■ Вы можете хранить и легко получать доступ к своим строкам в одном месте.

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

примечаниеВ некоторых программах-примерах из этой книги вы увидите, что я исполь­Зую объекты ResourceBundle для хранения запросов, передаваемых в (JueryDataSet.

Я решил рассказать вам про объект ResourceBundie Только потому, что он пред­ставляет хороший метод программирования В действительности, весь код, сгене­рированный в этом примере, достаточно хорошо написан, особенно впечатляет

примечаниеПрактика разделения кода приложения на код пользовательского интерфейса, нахо­дящийся в одном пакете, и невизуальный код, расположенный в другом пакете. Это является примером правильного метода создания Java-приложения.

Некоторые версии JBuiIder включают в себя мастер строк ресурсов (Resource Strings Wizard). Вы можете вызвать его через пункт меню Wizards ∣ Resource Strings.

Резюме

В этой главе вы ознакомились с инструментами автоматической генерации при­ложений, встроенными в JBuilder. Я попытался сделать несколько больше, чем про­сто провести вас через этапы создания кода. Был произведен определенный анализ кода, а также я попытался объяснить, что делает JBuilder и почему.

В последующих главах вы увидите, как создавать приложения с базами данных вручную. В главе 42 будет продемонстрировано, что еще можно сделать с помощью генератора приложений, взаимодействующих с базами данных.

Чарли Калверт

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *