Опубликован: 18.03.2010 | Уровень: специалист | Доступ: платный
Лекция 3:

Технология 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. Получение информации о курсах валют

Как видно на Рис. 3.36,система из клиентского приложения и компоненты EJB работает так же, как и раньше.

Пример "Корзина в интернет магазине"

Общее описание

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

Создание таблиц в базе данных
Инфологическая модель базы данных

увеличить изображение
Рис. 3.37. Инфологическая модель базы данных

Список товаров, сделанные заказы и их состав будут храниться в базе данных, инфологическая модель которой представлена на Рис. 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;
	}
}
Антон Зубеков
Антон Зубеков

Здравствуйте, подскажите пожалуйста где можно достать материалы по курсу Кросс-платформенные и многозвенные технологии, о которых говориться, к примеру, в Лекции 2. Пример "Служба мгновенных сообщений"

Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург
Ольга Малых
Ольга Малых
Россия, Казань, Университет управления "ТИСБИ"