Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2013_1 / КСТ / Разработка веб-приложений.pdf
Скачиваний:
160
Добавлен:
23.02.2015
Размер:
2.74 Mб
Скачать

19. Обработка связей внешних ключей

Используемое в технологии Java EE 6 отображение (mapping) полей записей

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

писи внешней таблицы, хранимого в записи БД, объект имеет свойство, содержащее

экземпляр сущности из внешней таблицы. В то же время экземпляр сущности внеш-

ней таблицы содержит список ссылающихся на него объектов.

Посмотрите внимательно на фрагмент объявления свойства personsList и методов доступа к этому свойству в сущности класса Cities:

@OneToMany(cascade = CascadeType.ALL, mappedBy = "cityId") private List<Persons> personsList;

public List<Persons> getPersonsList() { return personsList;

}

public void setPersonsList(List<Persons> personsList) { this.personsList = personsList;

}

Аннотация @OneToMany объявляет следующее за ним свойство связью «один-

ко-многим» между сущностями Cities и Persons через свойство cityId. Это свойство

задаётся при отображении записи БД в объект сущности подсистемой хранилища и поддерживается в актуальном состоянии при всех манипуляциях с сущностями и с записями БД.

Симметрично свойство связи внешнего ключа в описании класса Persons вы-

глядит так:

@JoinColumn(name = "city_id", referencedColumnName = "id_city") @ManyToOne(optional = false)

private Cities cityId;

а методы доступа — как:

public Cities getCityId() { return cityId;

}

public void setCityId(Cities cityId) { this.cityId = cityId;

}

Эта согласованная пара свойств обеспечивает потребности программиста и дизайнера при разработке приложения. Причина, по которой выбрано имя свойства cityId, заключается в том, что администратором базы данных так было названо поле

внешнего ключа при создании таблицы персон. Там это поле имело смысл ключа

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

232

19.1. Разработка класса для вида сущности

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

этого требуется создать виртуальное свойство-конвертор ключа записи в таблице го-

родов в объект сущности «город». Это вызвано тем, что используемый нами стан-

дартный компонент выбора из выпадающего списка возвращает ключ, а не объект с

таким ключом.

Для получения объекта-города с заданным ключом приходится обращаться

к услугам фасада городов, для чего его необходимо объявить в тексте класса вида

для персоны (смотрите п. 1.4.4.3: клик правой кнопкой после заголовка класса –

«Вставить код» – Call Enterprise Bean – выбор из списка имени фасада). Должны

быть вставлены строки:

@EJB

private CitiesFacade citiesFacade;

Метод Long getId_City() возвращает ключ объекта города персоны (если он не

был задан, то 1L — длинное целое).

public Long getId_City() {

return (this.person.getCityId() == null) ? 1L

: this.person.getCityId().getIdCity();

}

Метод setId_City(Long id) устанавливает значение свойства cityId персоны как объект с ключом, заданным параметром.

public void setId_City(Long id) { this.person.setCityId(citiesFacade.find(id));

}

Файл PersonsView.java package Views;

import Entities.Persons; import Facades.CitiesFacade; import Facades.PersonsFacade; import java.util.Date; import java.util.List; import javax.ejb.EJB;

import javax.enterprise.context.RequestScoped; import javax.faces.bean.ManagedBean;

/**

*

* @author cyx */

@ManagedBean(name = "personsView") @RequestScoped

public class PersonsView { @EJB

private CitiesFacade citiesFacade;

@EJB

private PersonsFacade personsFacade; private Persons person;

233

/** Creates a new instance of PersonsView */ public PersonsView() {

this.person = new Persons(null, "", "", "", new Date(1990, 01, 31));

}

public Persons getPerson() { return this.person;

}

public int getNumberOfPersons() { return personsFacade.findAll().size();

}

public List<Persons> getAllOfPersons() { return personsFacade.findAll();

}

public String savePerson() { this.personsFacade.create(person); return “personsPage”;

}

public String modPerson(Persons person) { this.person = person;

return “person_mod”;

}

public String mod_yes_Person() { this.personsFacade.edit(this.person); return “personsPage”;

}

public String delPerson(Persons person) { this.person = person;

return “person_del”;

}

public String del_yes_Person() { this.personsFacade.remove(this.person); return “personsPage”;

}

// Виртуальное свойство-конвертор id <--> City для выбора из списка Default 1L

public Long getId_City() {

return (this.person.getCityId() == null) ? 1L : this.person.getCityId().getIdCity();

}

public void setId_City(Long id) { this.person.setCityId(citiesFacade.find(id));

}

}

234

Упражнения

1.Как в текст класса попало объявление объекта citiesFacade?

2.Почему потребовалось объявлять виртуальное свойство id_City?

19.2. Доработка вида для городов

Для работы компонента выбора из выпадающего списка необходимо подгото-

вить свойство в классе вида для городов, содержащее форматированный специаль-

ным образом список элементов. Для этого вставим в файл класса CitiesView.java опи-

сание поля citiesSelector:

private ArrayList citiesSelector;

и метод getCitiesSelector() для вычисления свойства citiesSelector (не забывайте ис-

правлять выражения импорта).

public ArrayList getCitiesSelector() { citiesSelector = new ArrayList();

List<Cities> allCities = this.citiesFacade.findAll(); for (int i = 0; i < (allCities.size()); i++) {

Cities cit = allCities.get(i);

citiesSelector.add(new SelectItem(cit.getIdCity(), cit.getName(), cit.getName()));

}

return citiesSelector;

}

Список выбора представляет собой набор компонент класса SelectItem, содержащих ключ, название и описание элемента выбора. Проанализируйте текст метода.

19.3. Разработка обзорной страницы

Структура файла personsPage.xhtml для генерации обзорной таблицы персон не сильно отличается от таблицы городов. Существенным отличием является поле

города для персоны. Для его визуализации используется выражение

“#{person.cityId.name}”,

в котором для показа названия города использовано свойство name города, на который ссылается поле cityId для person.

Обратите внимание на форматирование дат с использованием тега convertDateTime, вложенного в тег outputText. Это позволяет видеть дату в формате dd.mm.YY, который часто употребляется в деловой переписке. Изменяя значение атри-

бута dateStyle на default, short, medium, long и full, можно получить нужный формат.

<h:outputText value="#{person.bday}"> <f:convertDateTime dateStyle="short" />

</h:outputText>

235

Файл personsPage.xhtml

<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:ui="http://java.sun.com/jsf/facelets"

>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

<title>Просмотр таблицы персон</title> </head>

<body>

<f:view>

<table border="1" width="100%"> <tr>

<td><h:outputLabel value="Персоны. Всего записей "/> <h:outputText value="#{personsView.numberOfPersons}"/> </td>

</tr>

<tr>

<td>

<h:form>

<h:dataTable value="#{personsView.allOfPersons}" var="person" border="1">

<h:column>

<f:facet name="header"> <h:outputText value="Ключ"/>

</f:facet>

<h:outputText value="#{person.idPerson}"/> </h:column>

<h:column>

<f:facet name="header"> <h:outputText value="Фамилия"/>

</f:facet>

<h:outputText value="#{person.family}"/> </h:column>

<h:column>

<f:facet name="header"> <h:outputText value="Имя"/>

</f:facet>

<h:outputText value="#{person.name}"/> </h:column>

<h:column>

<f:facet name="header"> <h:outputText value="Отчество"/>

</f:facet>

<h:outputText value="#{person.father}"/> </h:column>

<h:column>

<f:facet name="header">

236

<h:outputText value="Дата рождения"/> </f:facet>

<h:outputText value="#{person.bday}"> <f:convertDateTime dateStyle="short" />

</h:outputText>

</h:column>

<h:column>

<f:facet name="header"> <h:outputText value="Город"/>

</f:facet>

<h:outputText value="#{person.cityId.name}"/> </h:column>

<h:column>

<f:facet name="header"> <h:outputText value="Операции"/>

</f:facet>

<h:commandLink action="#{personsView. modPerson(person)}">

<h:outputText value="Заменить" /> </h:commandLink>

<h:commandLink action="#{personsView. delPerson(person)}">

<h:outputText value="Удалить" /> </h:commandLink>

</h:column>

</h:dataTable>

</h:form>

</td>

</tr>

<tr>

<td>

<h:form>

<h:commandLink action="personAddPage"> <h:outputText value="Добавить" />

</h:commandLink>

</h:form>

<br/>

<h:form>

<h:commandLink action="index"> <h:outputText value="На главную" />

</h:commandLink>

</h:form>

</td>

</tr>

</table>

</f:view>

</body>

</html>

237

Упражнения

1.Проследите путь информации о названии города для персоны.

2.Проверьте различные форматы вывода дат.

19.4.Страница для добавления записей

свнешними ключами

Особенность страницы ввода заключается в наличии поля внешнего ключа, ко-

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

этого используется компонент selectOneMenu, атрибут value которого ссылается на

виртуальное(вычисляемое)свойствоid_CityэкземпляравидадляперсонpersonsView.

Напомним, что это свойство-конвертор «ключ – объект» описано в виде для персоны.

Вложенный тег selectItems задаёт своим атрибутом value ссылку на виртуальное свойство citiesSelector экземпляра вида для городов citiesView, которое и вычисляет необ-

ходимый список элементов выбора для селектора.

<h:selectOneMenu

id="idCity"

required

=

"true"

value

=

"#{personsView.id_City}" >

<f:selectItems value="#{citiesView.citiesSelector}" /> </h:selectOneMenu>

Файл personAddPage.xhtml

<?xml version="1.0" encoding="UTF-8"?>

<!--

To change this template, choose Tools | Templates and open the template in the editor.

-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"

xmlns:h="http://java.sun.com/jsf/html"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:ui="http://java.sun.com/jsf/facelets"

>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>

<title>Добавление персоны в таблицу</title> </head>

<body>

<f:view>

<table border="1" width="100%"> <tr>

<td>

<h:form>

<table>

<tr>

<td> <h:outputLabel value="Фамилия:"/> </td>

238

<td><h:inputText value="#{personsView.person.

family}"/> </td>

</tr>

<tr>

<td> <h:outputLabel value="Имя:"/> </td> <td><h:inputText value="#{personsView.person.

name}"/> </td>

</tr>

<tr>

<td> <h:outputLabel value="Отчество:"/> </td> <td><h:inputText value="#{personsView.person.

father}"/> </td>

</tr>

<tr>

<td> <h:outputLabel value="Рождение:"/> </td> <td><h:inputText value="#{personsView.person.

bday}">

<f:convertDateTime dateStyle="short" /> </h:inputText>

</td>

</tr>

<tr>

<td> <h:outputLabel value="Город:"/> </td> <td>

<h:selectOneMenu id="idCity" required = "true" value =

"#{personsView.id_City}" >

<f:selectItems value="#{citiesView.citiesSe-

lector}" />

<!--f:converter / --> </h:selectOneMenu>

</td>

</tr>

<tr>

<td>

<h:commandButton action="#{personsView.

savePerson}"

value="Добавить" /> <h:commandButton action="personsPage" value="Отменить" />

</td>

</tr>

</table>

</h:form>

</td>

</tr>

</table>

</f:view>

</body>

</html>

239

Соседние файлы в папке КСТ