Интерфейс org.hibernate.Session
является мостом между приложением и Hibernate.
С помощью сессий выполняются все CRUD-операции с объектами-сущностями.
Объект типа Session
получают из экземпляра типа org.hibernate.SessionFactory
,
который должен присутствовать в приложении в виде singleton.
Жизненный цикл session
ограничен началом и концом логической транзакции.
- Transient object -- заполненные экземпляры классов-сущностей. Могут быть
сохранены в БД. Не присоединены к сессии. Поле
Id
не должно быть заполнено, иначе объект имеет статусdetached
. - Persistent object -- так называемая хранимая сущность, которая присоединена к конкретной сессии. Только в этом статусе объект взаимодействует с базой данных. При работе с объектом данного типа в рамках транзакции все изменения объекта записываются в базу.
- Detached object -- объект, отсоединённый от сессии, может существовать или не существовать в БД.
Любой объект-сущность можно переводить из одного статуса в другой. Для этого в
интерфейсе Session
существуют следующие методы:
-
persist(Object) -- преобразует объект из transient в persistent, то есть присоединяет к сессии и сохраняет в БД. Однако, если мы присвоим значение полю
Id
объекта, то получимPersistentObjectException
, т.к. Hibernate посчитает, что объект detached, т.е. существует в БД. При сохранении метод persist() сразу выполняет insert, не делая select. -
merge(Object) -- преобразует объект из transient или detached в persistent. Если из transient, то работает аналогично persist() (генерирует для объекта новый
Id
, даже если он задан), если из detached — загружает объект из БД, присоединяет к сессии, а при сохранении выполняет запрос update. -
replicate(Object, ReplicationMode) -- преобразует объект из detached в persistent, при этом у объекта обязательно должен быть заранее установлен
Id
. Данный метод предназначен для сохранения в БД объекта с заданнымId
, чего не позволяют сделать persist() и merge(). Если объект с даннымId
уже существует в БД, то поведение определяется согласно правилу из перечисленияorg.hibernate.ReplicationMode
:- ReplicationMode.IGNORE — ничего не меняется в базе.
- ReplicationMode.OVERWRITE — объект сохраняется в базу вместо существующего.
- ReplicationMode.LATEST_VERSION — в базе сохраняется объект с последней версией.
- ReplicationMode.EXCEPTION — генерирует исключение.
-
delete(Object) -- удаляет объект из БД, иными словами, преобразует persistent в transient. Object может быть в любом статусе, главное, чтобы был установлен
Id
. -
save(Object) -- сохраняет объект в БД, генерируя новый
Id
, даже если он установлен. Object может быть в статусе transient или detached. -
update(Object) -- обновляет объект в БД, преобразуя его в persistent (Object в статусе detached).
-
saveOrUpdate(Object) -- вызывает save() или update().
-
refresh(Object) -- обновляет detached-объект, выполнив select к БД, и преобразует его в persistent.
-
get(Object.class, id) -- получает из БД объект класса-сущности с определённым
Id
в статусе persistent.
Объект Session
кэширует у себя загруженные объекты, при загрузке объекта из
БД в первую очередь проверяется кэш. Для того, чтобы удалить объект из кэша
и отсоединить от сессии, используется session.evict(Object)
. Метод
session.clear()
применит evict()
ко всем объектам в сессии.
Является интерфейсом ORM, служит для управления персистентными сущностями.
Управление сущностями начинается с создания EntityManagerFactory
, которая отвечает за отображение объектов в базу, поддержку соединений, кэш состояний и всякие такие вещи.
Фабрика создает объекты EntityManager
, который может управлять сущнастями. EntityManager
может образовать persistence context - набор экземпляров сущностей, загруженных из БД или созданных (является своего рода кэшем данных в рамках транзакции). EntityManager сбрасывает в БД все изменения в персистентном контексте в момент коммита транзакции, либо при явном вызове метода flush().
-
persist() -- вводит новый экземпляр managed сущности в persistence context. При коммите транзакции командой SQL INSERT в БД будет создана соответствующая запись.
-
merge() -- переносит состояние detached сущности в persistence context: из БД загружается экземпляр с тем же id, в него переносится состояние переданного Detached экземпляра и возвращается загруженный Managed экземпляр. Далее надо работать именно с возвращенным Managed экземпляром.
-
remove() -- удаляет объект из бд, либо, если включен режим мягкого удаления, установит атрибуты deleteTs и deletedBy.
-
find() -- загружает экземпляр сущности по идентификатору.
-
fetch() -- обеспечивает для экземпляра сущности загрузку всех атрибутов указанного представления, включая lazy атрибуты. Экземпляр сущности должен быть в Managed состоянии.
-
reload() -- перезагрузить экземпляр сущности с указанным представлением. Обеспечивает загрузку всех атрибутов представления, вызывая внутри себя метод fetch().
1. Технология JavaServer Faces. Особенности, отличия от сервлетов и JSP, преимущества и недостатки. Структура JSF-приложения.
JavaServer Faces (JSF) — это фреймворк для веб-приложений, для разработки пользовательских интерфейсов Java EE приложений. Основывается на использовании компонентов. Состояние компонентов пользовательского интерфейса сохраняется, когда пользователь запрашивает новую страницу и затем восстанавливается, если запрос повторяется.
- Четкое разделение бизнес-логики и интерфейса
- Управление на уровне компонент
- Простая работа с событиями на стороне сервера
- Расширяемость
- Доступность нескольких реализаций от различных компаний-разработчиков
- Широкая поддержка со стороны интегрированных средств разработки (IDE)
- Высокоуровневый фреймворк — сложно реализовывать не предусмотренную авторами функциональность.
- Сложности с обработкой GET-запросов (устранены в JSF 2.0).
- Сложность разработки собственных компонентов.
- JSP-страницы с компонентами GUI
- Библиотека тегов
- Управляемые бины
- Доп. объекты(компоненты, конвертеры, вылидаторы)
- Доп. теги
- Конфигурация – faces-config.xml
- Дискриптор развертывания – web.xml
Интерфейс JSF-приложения состоит из страниц JSP (Java Server Pages), которые содержат компоненты, обеспечивающие функциональность интерфейса. При этом библиотеки тегов JSP используются на JSF-страницах для отрисовки компонентов интерфейса, регистрации обработчиков событий, связывания компонентов с валидаторами и конвертаторами данных и много другого.
При этом нельзя сказать, что JSF неразрывно связана с JSP, т.к. теги, используемые на JSP-страницах только отрисовывают компоненты, обращаясь к ним по имени. Жизненный же цикл компонентов JSF не ограничивается JSP-страницей.
3. JSF-компоненты - особенности реализации, иерархия классов. Дополнительные библиотеки компонентов. Модель обработки событий в JSF-приложениях.
- Интерфейс строится из компонентов.
- Компоненты расположены на страницах JSP.
- Компоненты реализуют интерфейс javax.faces.component.UIComponent.
- Можно создавать собственные компоненты.
- Компоненты на странице объединены в древовидную структуру — представление.
- Корневым элементов представления является экземпляр класса javax.faces.component.UIViewRoot.
Некоторые компоненты JSF: <f:subview>
, <h:selectOneMenu>
, <h:selectOneRadio>
, <h:selectOneListbox>
, <h:selectManyCheckbox>
, <selectManyListbox>
, <selectManyMenu>
, <h:textArea>
, ...
<h:selectOneListbox id="type" value="#{contactController.contact.type}">
<f:selectItem itemValue="PERSONAL" itemLabel="personal"/>
<f:selectItem itemValue="BUSINESS" itemLabel="business"/>
</h:selectOneListbox>
-- javax.faces.component.UIComponent
---- javax.faces.component.UIComponentBase
------ javax.faces.component.UIOutput
-------- javax.faces.component.UIInput
---------- javax.faces.component.UISelectOne
---------- javax.faces.component.UISelectMany
PrimeFaces, RichFaces, ICEFaces, OpenFaces, Trinidad, Tomahawk.
- Восстановление представления
- Использование параметров запроса; обработка событий
- Проверка данных; обработка событий
- Обновление данных модели; обработка событий
- Вызов приложения; обработка событий
- Фаза формирования представления. JSF Runtime формирует представление по запросу(request) пользователя: создаются объекты компонентов, назначаются слушатели событий, конвертеры и валидаторы, все элементы представления помещаются в FacesContext
- Фаза получения значений компонентов. Вызывается конвертер из стокового типа данных в требуемый тип. Если конвертация успешна, то значение сохраняется в локальной переменной компонента. Если неуспешно – создается сообщение об ошибке и помещается в FacesContext.
- Фаза валидации значений компонентов. Вызываются валидаторы, зарегистрированные для компонентов представления. Если значение компонента не проходит валидацию, создается сообщение об ошибке и сохраняется в FacesContext.
- Фаза обновления значений компонентов. Если данные валидны, то значение компонента обновляется. Новое значение присваивается полю объекта компонента.
- Фаза вызова приложения. Управление передается слушателям событий. Формируются новые значение компонентов.
- Фаза формирования ответа сервера. Обновляется представление в соответствии с результатом обработки запроса. Если это первый запрос к странице, то компоненты помещаются в иерархию представления. Формируется ответ сервера на запрос(response). На стороне клиента происходит обновление страницы.
JSF имеет встроенные конвенторы и позволяет создавать специализированные.
- javax.faces.BigDecimal
- javax.faces.BigInteger
- javax.faces.Boolean
- javax.faces.Byte
- javax.faces.Character
- javax.faces.DateTime
- javax.faces.Double
- javax.faces.Float
<h:outputLabel value="Age" for="age" accesskey="age" />
<h:inputText id="age" size="3" value="#{contactController.contact.age}">
</h:inputText>
<h:outputLabel value="Birth Date" for="birthDate" accesskey="b" />
<h:inputText id="birthDate" value="#{contactController.contact.birthDate}">
<f:convertDateTime pattern="MM/yyyy"/>
</h:inputText>
- Создать класс, реализующий интерфейс Converter
- Реализовать метод getAsObject(), для преобразования строкового значения поля в объект.
- Реализовать метод getAsString.
- Зарегистрировать конвертер в контексте Faces в файле faces-config.xml, используя элемент .
файл faces-config.xml
<converter>
<converter-for-class>
com.arcmind.contact.model.Group
</converter-for-class>
<converter-class>
com.arcmind.contact.converter.GroupConverter (com.arcmind.contact.converter.TagConverter)
</converter-class>
</converter>
- С помощью встроенных компонентов
- На уровне приложения
- С помощью проверочных методов серверных объектов (inline-валидация)
- С помощью специализированных компонентов, реализующих интерфейс Validator
- DoubleRangeValidator
- LongRangeValidator
- LengthValidator
<%-- возраст (age) --%>
<h:outputLabel value="Age" for="age" accesskey="age" />
<h:inputText id="age" size="3" value="#{contactController.contact.age}">
<f:validateLongRange minimum="0" maximum="150"/>
</h:inputText>
<h:message for="age" errorClass="errorClass" />
Это непосредственно бизнес-логика. Заключается в добавлении в методы управляемых bean-объектов кода, который использует модель приложения для проверки уже помещенных в нее данных.
Для типов данных, не поддерживаемых стандартными валидаторами, например, адресов электронной почты, можно создавать собственные валидирующие компоненты
JSF позволяет создавать подключаемые валидирующие компоненты, которые можно использовать в различных Web-приложениях.
Это должен быть класс, реализующий интерфейс Validator, в котором реальзован метод validate(). Необходимо зарегистрировать валидатор в файле faces-config.xml. После этого можно использовать тег <f:validator/> на страницах JSP.
faces-config.xml
<validator>
<validator-id>arcmind.zipCode</validator-id>
<validator-class>com.arcmind.validators.ZipCodeValidator</validator-class>
</validator>
За представление отвечают:
UI Component
. Объект с состоянием, методами, событиями, который содержится на сервере и отвечает за взаимодействие с пользователем (визуальный компонент). Каждый UI компонент содержит метод метод render
для прорисовки самого себя, согдасно правилам в классе Render
Renderer
- Отвечает за отображение компонента и преобразование ввода пользователя
Validator
, Convertor
Backing bean
- собирает значения из компонент, реагирует на события, взаимодействует с бизнес-логикой.
Events
, Listeners
, Message
Navigation
- =правила навигации между страницами, задаются в виде xml документа
Объект UIViewRoot
дает представдение JSF, он связан с активным FacesContext. JSF реализация создаёт представление при первом обращении (запросе), либо восстанавливает уже созданное. Когда клиент отправляет форму (postback), JSF конвертирует отправленные данные, проверяет их, сохраняет в managed bean, находит представление для навигации, восстанавливает значения компонента из managed bean, генерирует ответ по представлению. Все эти действия JSF описываются с помощью 6 упорядоченных процессов.
Управляемые бины – классы, содержащие параметры и методы для обработки данных с компонентов. Должны иметь методы get
и set
/ Используются для обработки UI и валидации данных. Жихненным цикллом управляет JSF Runtime Env. Доступ из JSP-страниц осуществляется с помощью языка выражений (EL). Конфигурация задается либо в faces-config.xml, либо с помощью аннотаций.
faces-config.xml
<managed-bean>
<managed-bean-name>customer</managed-bean-name>
<managed-bean-class>CustomerBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>areaCode</property-name>
<value>#{initParam.defaultAreaCode}</value>
</managed-property>
</managed-bean>
С помощью аннотаций
@ManagedBean(name="customer")
@RequestScoped
public class CustomerBean {
@ManagedProperty(value="#{initParam.defaultAreaCode}" name="areaCode")
private String areaCode;
...
}
Managed bean
- бин, зарегистрированный в JSF, управляется JSF платформой. Мanaged bean используются в качестве модели для компонентов и имеют свою область жизни (scope), которую можно задать при помощи аннотации или в конфигурационном файле faces-config.xml.
У управляемых бинов есть контекст, который оперделяет продолжительность жизни. Он задается аннотацией.
@RequestScoped
- используется по умолчанию. Создаётся новый экземпляр managed bean на каждый HTTP запрос (и при отправке, и при получении). Контекст - запрос
@SessionScoped
- экземпляр создаётся один раз при обращении пользователя к приложению, и используется на протяжении жизни сессии. Managed bean обязательно должен быть Serializable. Контекст — сессия.
@ApplicationScoped
- экземпляр создаётся один раз при обращении и используется на протяжении жизни всего приложения. Не должен иметь состояния, а если имеет, то должен синхронизировать доступ, так как доступен для всех пользователей. Контекст — приложение.
@ViewScoped
- экземпляр создаётся один раз при обращении к странице, и используется ровно столько, сколько пользователь находится на странице (включая ajax запросы). Контекст — страница, представление.
@CustomScoped(value="#{someMap}")
- экземпляр создаётся и сохраняется в Map. Программист сам управляет областью жизни.
@NoneScoped
- экземпялр создаётся, но не привязывается ни к одной области жизни. Применяется когда к нему обращаются другие managed bean'ы, имеющие область жизни. Бин без контекста.
faces-config.xml — конфигурационный файл JavaServer Faces, который должен находиться в директории WEB-INF проекта. В этом файле могут находиться настройки managed bean, конвертеры, валидаторы, локализация, навигации и другие настройки, связанные с JSF
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
<managed-bean>
<managed-bean-name>calculator</managed-bean-name>
<managed-bean-class>com.arcmind.jsfquickstart.model.Calculator</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>
Объявление управляемого объекта: имя объекта задается с помощью <managed-bean-name>
, полное имя класса - <managed-bean-class>
. Класс управляемого объекта обязан содержать конструктор без параметров.
<managed-bean-scope>
определяет, где JSF будет искать объект. Если объект привязан к представлению и не существует на момент обращения, то JSF создаст его автоматически с помощью API универсального языка выражений EL. Объект будет доступен в течение обработки одного запроса.
По умолчанию используется faces-config, но можно использовать дополнительные конфиги, перечислив их в web.xml.
- Обрабатывает запросы с браузера.
- Формирует объекты-события и вызывает методы-слушатели.
Механизм нафигации JSF позволяет определить связь между логическим признаком результата и следующим представлением. Реализуется объектами NavigationHandler
. Навигация осуществляется с помощью правил перехода.
Ссылку можно добавить тремя различными способами:
- С помощью commandLink и обычного правила перехода, определяемого в faces-config.xml
<navigation-rule>
<navigation-case>
<from-outcome>CALCULATOR</from-outcome>
<to-view-id>/pages/calculator.jsp</to-view-id>
</navigation-case>
</navigation-rule>
-
С помощью commandLink и правила перехода, использующего элемент .
-
Связывание с помощью прямой ссылки (элемента <h:outputLink>)
<h:outputLink value="pages/calculator.jsf">
<h:outputText value="Calculator Application (outputlink)"/>
</h:outputLink>