|
Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 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;
}
}

