Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 2. Пример "Служба мгновенных сообщений" |
Технология Enterprise Java Beans. Часть 1
Пример "Модифицированный конвертор валют с базой данных"
Другой способ подключения к базе данных
Предыдущий пример можно несколько упростить при помощи встроенных возможностей JBoss.Сервер JBoss поддерживает встроенный пул соединений к базам данных. Эти соединения можно получать из компонента EJB при помощи JNDI.Для того чтобы сконфигурировать подключение к новой базе данных можно для начала посмотреть файлов конфигураций для различных баз данных. Они находятся в каталоге docs/examples/jca установочного каталога JBoss.Нас интересует файл oracle-ds.xml. Здесь уже представлен вариант этого файла, в который вставлены значения, соответствующие подключению к нашей базе данных.
Сделать копию проекта в Eclipse можно щелкнув правой кнопкой мыши на проекте слева и выбрав в меню пункт Copy.
<?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <!-JNDI имя, по которому мы будет получать подключение--> <jndi-name>OracleDS</jndi-name> <!-Строка подключения к БД--> <connection-url> jdbc:oracle:thin:@localhost:1521:ejbdb </connection-url> <!-Класс драйвера БД--> <driver-class>oracle.jdbc.OracleDriver</driver-class> <!-Имя пользователя в БД и пароль--> <user-name>boris</user-name> <password>quasimodo</password> <exception-sorter-class-name> org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter </exception-sorter-class-name> <!-Название описания соответствий типов--> <metadata> <type-mapping>Oracle9i</type-mapping> </metadata> </local-tx-datasource> </datasources>
Далее этот файл необходимо скопировать в каталог server\default\deploy установочного каталога JBoss.
Класс компонента
Для того, чтобы использовать новый способ подключения к базам данных требуется изменить только класс компонента. В нем необходимо переопределить метод setSessionContext(SessionContext arg) следующим образом:
public void setSessionContext(SessionContext arg0) throws EJBException, RemoteException { try { InitialContext ctx = new InitialContext(); if (dataSource == null) // Получаем объект DataSource из JNDI контекста dataSource = (DataSource) ctx.lookup("java:/OracleDS"); System.out.println("Data source aquired"); } catch (NamingException ex) { throw new EJBException(ex); } }
Теперь метод convert будет выглядеть так:
public double convert(String cur1, String cur2, double amount) throws CurrencyRateNotFoundUpgException { if (dataSource == null) { return -1; } try { // Получаем подключение к базе данных из пула соединений Connection conn = dataSource.getConnection(); // Готовим SQL-команду к выполнению PreparedStatement p = conn.prepareStatement ("SELECT RATE FROM CURRENCY_EXCHANGE_RATE " + "WHERE CUR1NAME=? AND CUR2NAME=?"); p.setString(1, cur1); p.setString(2, cur2); ResultSet r = p.executeQuery(); // Обрабатываем полученный результат if (r.next()) { double rate = r.getDouble(1); return rate * amount; } else { throw new CurrencyRateNotFoundUpgException(cur1, cur2); } } catch (SQLException e) { e.printStackTrace(); } return -1; }
Размещаем компонент на сервере JBoss и запускаем клиентское приложение.
Как видно на Рис. 3.36,система из клиентского приложения и компоненты EJB работает так же, как и раньше.
Пример "Корзина в интернет магазине"
Общее описание
Теперь будет рассмотрен несколько более сложный пример, чем предыдущие примеры. В нем будет продемонстрирована работа такого компонента, имеющегося у большинства интернет магазинов как корзина с покупками. Пользователь, зайдя на страницу нашего магазина сможет залогиниться, введя свое имя, просмотреть список доступных товаров, добавить необходимые ему товары в корзину, сделать заказ, пересчитать количество отдельных товаров в заказе, а также просмотреть свои предыдущие заказы. Торговать интернет магазине будет сигаретами.
Создание таблиц в базе данных
Список товаров, сделанные заказы и их состав будут храниться в базе данных, инфологическая модель которой представлена на Рис. 3.37. Эта база данных состоит из трех основных таблиц:
- Таблицы COMMODITIESLIST, в которой хранится информация о всех доступных товарах в магазине. Поле NAME - название товара, DESCRIPTION - его описание, PRICE - цена в долларах США, а необязательное поле IMAGEPATH - идентификатор изображения, соответствующее товару (используется при отображении списка товаров в интернете).
- Таблицы ORDERS, в которой хранится информация о заказе. DATE_CREATED - дата, когда заказ был сделан и USERNAME - имя пользователя, сделавшего заказ.
- Таблицы COMMODITYORDER, которая описывает товары, из которых состоит заказ. ORDERID - идентификатор заказа, COMMODITYID -идентификатор товара, QUANTITY - количество экземпляров этого товара в заказе. ORDERID И COMMODITYID связаны с таблицами COMMODITIES_LIST и ORDERS по внешнему ключу.
Для того, чтобы создать таблицы в базе данных Oracle 9i,необходимо выполнить следующий SQL-код.Помимо создания таблиц в базе данных, данный SQL-код заполняет таблицы некоторым набором значений по умолчанию. Для каждой таблицы определен триггер, автоматически генерирующий поле ID для каждой добавленной строки таблицы. Вначале создается пакет ORDER_ID_PKG, в котором определена переменная, хранящая целое значение, и функция ее возвращающая. Триггер, генерирующий поле ID для таблицы ORDERS, сохраняет новое сгенерированное значение в поле LAST_ID пакета ORDER_ID_PKG. Это сделано для того, чтобы получить ID последнего добавленного заказа и использовать его при добавлении строк в таблицу COMMODITY_ORDER.
create or replace package ORDER_ID_PKG as LAST_ID integer; function GET_LAST_ID return integer; end ORDER_ID_PKG; / create or replace package body ORDER_ID_PKG as function GET_LAST_ID return integer is begin return LAST_ID; end GET_LAST_ID; end ORDER_ID_PKG; / create table COMMODITIES_LIST ( ID integer not null, NAME varchar(20) not null, DESCRIPTION varchar(50) not null, PRICE float not null, IMAGEPATH varchar(30), primary key(ID)); create sequence COMMODITIES_SEQ start with 1 increment by 1 nomaxvalue; create trigger COMMODITIES_TRIGGER before insert on COMMODITIES_LIST for each row begin select COMMODITIES_SEQ.nextval into :new.id from dual; end; / insert into COMMODITIES_LIST(NAME, DESCRIPTION, PRICE, IMAGEPATH) values('Kent 1', 'Normal cigarettes', 1.99, 'img/kent1.jpg'); insert into COMMODITIES_LIST(NAME, DESCRIPTION, PRICE, IMAGEPATH) values('Kent 4', 'Light cigarettes', 1.99, 'img/kent4.jpg'); insert into COMMODITIES_LIST(NAME, DESCRIPTION, PRICE, IMAGEPATH) values('Kent 8', 'Very light cigarettes', 1.99, 'img/kent8.jpg'); insert into COMMODITIES_LIST(NAME, DESCRIPTION, PRICE, IMAGEPATH) values('Lucky Strike', 'Pure American Taste', 2.30, 'img/lucky.jpg'); insert into COMMODITIES_LIST(NAME, DESCRIPTION, PRICE, IMAGEPATH) values('Portugas', 'Fine Cuban Cigar', 10.95, 'img/portugas.jpg'); select * from COMMODITIES_LIST; / create table ORDERS ( ID integer not null, DATE_CREATED DATE not null, USERNAME varchar(20) not null, primary key(ID) ); create sequence ORDERS_SEQ start with 1 increment by 1 nomaxvalue; create trigger ORDERS_TRIGGER before insert on ORDERS for each row begin select ORDERS_SEQ.nextval into :new.id from dual; end; / create table COMMODITY_ORDER ( ID integer not null, ORDER_ID integer not null, COMMODITY_ID integer not null, QUANTITY integer not null, primary key(ID) ); alter table COMMODITY_ORDER add constraint FK_ORDER foreign key (ORDER_ID) references ORDERS(ID); alter table COMMODITY_ORDER add constraint FK_COMMODITIES foreign key(COMMODITY_ID) references COMMODITIES_LIST(ID); create sequence COMMODITY_ORDER_SEQ start with 1 increment by 1 nomaxvalue; create trigger COMMODITY_ORDER_TRIGGER before insert on COMMODITY_ORDER for each row begin select COMMODITY_ORDER_SEQ.nextval into :new.id from dual; end; /
Если таблицы уже созданы в базе данных, то необходимо предварительно выполнить следующий SQL-код,который удалит эти таблицы и последовательности при помощи которых генерировалось автоматически значение основного ключа строки в таблице.
drop table COMMODITY_ORDER; drop table ORDERS; drop table COMMODITIES_LIST; drop sequence COMMODITY_ORDER_SEQ; drop sequence COMMODITIES_SEQ; drop sequence ORDERS_SEQ;
Стоит сделать несколько замечаний - для таблицы COMMODITYORDER выполняется операция drop в самом начале кода. Это сделано из-за того, что таблица COMMODITYORDER связана внешним ключом с двумя другими таблицами. БД Oracle не даст нам выполнить операцию drop для двух других таблиц, пока связь посредством внешнего ключа с таблицей COMMODITYORDER.
Для того чтобы соотнести объекты из базы данных с Java -классами был создан класс абстрактный класс DataItem. В нем есть поле id, которое соответствует ID объекта в базе данных (как было описано выше, у любого объекта в этой базе данных есть свой ID ). Класс находится в пакете dataObjects.
public abstract class DataItem implements Serializable { protected int id = -1; public int getId() { return id; } public void setId(int id) { this.id = id; } }
От класса DataItem наследуются три других класса - Commodity, CommodityOrder и Order.Commodity соответствует товару из таблицы COMMODITY_LIST, CommodityOrder - товару из заказа в таблице COMMODITY_ORDERS, Order - заказу из таблицы ORDERS.
Исходный код класса Commodity представлен далее:
public class Commodity extends DataItem { private static final long serialVersionUID = -7004067843847157531L; private String name; private String description; private String imagePath; private double price; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public String getImagePath() { return imagePath; } public void setImagePath(String imagePath) { this.imagePath = imagePath; } public String toString() { return "ID=" + id + "; NAME=" + name + "; DESCRIPTION" + description + "; PRICE=" + price + "; IMAGEPATH=" + imagePath; } }
Исходный код класса CommodityOrder представлен далее:
public class CommodityOrder extends DataItem { private static final long serialVersionUID = -592875988844838475L; private int commodityId; private int commodityQuantity; public int getCommodityId() { return commodityId; } public void setCommodityId(int commodityId) { this.commodityId = commodityId; } public int getCommodityQuantity() { return commodityQuantity; } public void setCommodityQuantity(int commodityQuantity) { this.commodityQuantity = commodityQuantity; } }
Исходный код класса Order представлен далее:
public class Order extends DataItem { private static final long serialVersionUID = -3276613990865210869L; private String name; private Date date; public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }