Добавить в избранное   Сделать стартовой   Главная   E-mail   Форум   Мой блог 
   
Cертификации

Errors

ETL

FAQ (по темам)

GIS

Web

wiki

Администрирование

Безопасность

Книги
Oracle, ...

Новости

ОС

Программирование

Проектирование БД

Производительность

Скачать

Советы

Тестирование

Установка

FAQ - по базам данных
FAQ - по базам данных
Установка СУБД
Oracle
Sybase
MySQL
PostgreSQL
MS SQL Server
Interbase, Firebird
Другие DB
Администрирование
Oracle
MySQL
Sybase
PostgreSQL
MS SQL Server
Interbase, Firebird
IBM DB2
Другие DB
Проектирование БД
Статьи
ETL
Теория БД
ErWin
Designer 2000
PowerDesigner
Хранилища данных
CASE средства
OLAP
Бизнес - анализ (BI)
Производительность
Oracle
MSSQL
Interbase, Firebird
IBM DB2
MySQL
PostgreSQL
SYBASE
Безопасность БД
Oracle
MS SQL Server
Инъекция SQL
Программирование
Transact-SQL
PL/SQL
C++
XML
SQL
PostgreSQL
MDX
Java
VBA Excel
Книги по базам
Oracle
Заказ книг
ОС
Установка и настройка
UBUNTU
ОС
Установка и настройка
UBUNTU
FAQ
FAQ - по базам данных
Главная arrow Java arrow Примеры использования HIBERNATE Native SQL для выборки информации из базы данных

Примеры использования HIBERNATE Native SQL для выборки информации из базы данных

Печать E-mail

Примеры использования HIBERNATE Native SQL для выборки информации из базы данных

 Для некоторых приложений средств HQL бывает недостаточно и возникает необходимость использовать родной SQL вашей СУБД. Элементарный пример -- вызов хранимой процедуры БД.

В Hibernate для исполнения "родных" запросов служит метод

createSQLQuery(String queryString)

объекта

org.hibernate.Session

, который возвращает екземпляр

org.hibernate.SQLQuery

. Напомню, что для запросов на языке HQL используется метод

createQuery(String queryString)

того же класса, который возвращает екземпляр

org.hibernate.Query

. Класс

org.hibernate.SQLQuery

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

Во всех примерах екземпляр класса

org.hibernate.Session

называется

sess

. Он может быть получен стандартным способом:

new Configuration().configure().buildSessionFactory().getCurrentSession();

Класс

SomeClass

здесь называется отображенным, если для него существует

SomeClass.nbm.xml

, который зарегистрирован в

hibernate.cfg.xml

. Класс имеет свойство

property

, если в нем определены публичные методы

setProperty

и

getProperty

(setter и getter) для соответствующего поля property согласно соглашению Sun по наименованию

методов класоов:

property: setProperty/getProperty
proPerty: setProPerty/getProPerty
PROPERTY: setPROPERTY/getPROPERTY

Для демонстрации примеров используется база данных Oracle, состоящая из двух таблиц, с

вязанных внешним ключом. Таблица

TREE

содержит информацию о группах деревьев ботанического сада. Каждая такая группа имеет

уникальный номер, название, сорт (в группу входят деревья одного сорта) и количество

деревьев в группе. Таблица

SORT

содержит информацию о сортах деревьев ботанического сада.

Схема базы данных приведена ниже:

Схема базы данных

Диаграмма классов, отображенных на эти таблицы выглядит так:

Диаграмма классов

Связь между классами я здесь не показал — она очевидна.

Структура этих классов вместе с методами-акцессорами (getters & setters) в Eclipse:

Структура этих классов

Структура этих классов

Здесь не описана структура конфигурационных файлов (hibernate.cfg.xml, Tree.nbm.xml и

Sort.nbm.xml), так как объектно-реляционное отображение довольно тривиально и его легко

реализовать при необходимости самостоятельно.

Примеры

Выборка отображенных объектов одного класса

Задача. Необходимо получить список персистентных объектов класса

Tree

, который отображен в

hibernate.cfg.xml

.

Решение. Воспользуемся методом

createSQLQuery

для выполнения запроса. Обратите внимание: точка с запятой в конце запроса не ставится!

sess.createSQLQuery("SELECT * FROM TREE").addEntity(Tree.class).list();

В данном случае класс

Tree

должен быть отображен на таблицу

TREE

. Вызов

addEntity(Tree.class)

предписывает рассматривать результат запроса как набор классов

Tree

.

Выборка отображенных объектов разных классов в одном запросе

Задача. Получить декартово произведение таблиц

TREE

и

SORT

.

Решение.

session.createSQLQuery("select {tree.*}, {sort.*} from tree, sort").addEntity("tree", Tree.class).addEntity

("sort", Sort.class).list();

Код

{[aliasname}.*}

внутри запроса «подставляет» вместо себя в конечный запрос названия всех свойств

отображенного класса, который соотносится с алиасом aliasname. Таким образом, вместо

{tree.*}

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

tree.id, tree.name, tree.sort, tree.count

А вместо

{sort.*}

--

sort.id, sort.name

Во избежание конфликта имен (

id

есть в обоих классах) HIBERTNATE всегда подставляет сгенерированные алиасы, которые заканчиваются

цифрами и знаками подчеркивания. Именно поэтому код будет не такой же, как тот, что выше, а

эквивалентный ему.

Отдельно следует описать код который обрабатывает полученный список значений. Этот список содержит

объекты типа

Object[]

. Таким образом, результатом запроса будет список одномерных массивов базового типа

Object

. Для получения экземпляров классов

Tree

и

Sort

нужно сначала привести элемент списка к типу

Object[]

, а потом привести к нужному типу каждый из элементов этого массива.

Ниже приведен код, который выводит в стандартный поток результат декартового произведения таблиц

TREE

и

SORT

:

List list = session.createSQLQuery("select {tree.*}, {sort.*} from tree, sort").addEntity("tree", Tree.class).addEntity

("sort", Sort.class).list();

for (Object listelement : result) {
Object[] objectarray = (Object[]) listelement;
Tree tree = (Tree) objectarray[0];
Sort sort = (Sort) objectarray[1];
System.out.println("Tree: " + tree + ", sort: " + sort);
}

Обратите внимание на порядок объектов классов

Tree

и

Sort

в

objectarray

— он соответствует порядку следования

{tree.*}

и

{sort.*}

в запросе!

Выборка отображенных объектов связанных классов

Задача. Есть класс

Sort

, который отображен на таблицу

SORTS

. В классе

Tree

есть свойство

treeSort

типа

Sort

(таблицы

TREES

и

SORTS

связанны внешним ключом). Необходимо получить список персистентных объектов класса

Tree

вместе с объектами

Sort

, на которые они ссылаются.

Решение.

sess.createSQLQuery("SELECT * FROM TREE").addEntity("tree", Tree.class).addJoin("tree.treeSort").list();

 

Выборка неотображенных объектов

Задача. Получить количество деревьев всех сортов. Результат выборки представить в виде POJO,

который не отображен в файле конфигурации HIBERNATE.

Решение. Создаем класс

SortCount

со свойствами

String sortName

и

int countOfSort

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

session.createSQLQuery("select name sortname, sum(count) countofsort from tree, sort where tree.sort=sort.id

group by sortname")

.addScalar("sortName", Hibernate.STRING).addScalar("countOfSort", Hibernate.INTEGER).setResultTransformer

(Transformers.aliasToBean(SortCount .class)).list();

Метод

addScalar(String string, Type type)

подсказывает HIBERNATE названия и тип полей результата запроса, а цепочка методов

setResultTransformer(Transformers.aliasToBean(Contact.class)).list()

“превращает“ его в список объектов класса

SortCount

. Если убрать из кода оба метода

addScalar

, возникнет исключение

org.hibernate.PropertyNotFoundException

, вызванное отсутствием в классе

Contact

сеттеров для свойств

SORTNAME

и

COUNTOFSORT

. Причина возникновения исключения в том, что большинство СУБД регистронезависимые и

передают названия полей результата запроса в составе

ResultSetMetaData

в верхнем регистре. Как следствие — названия свойств

SORTNAME

и

COUNTOFSORT

, а не

sortName

и

countOfSort

. Один из вариантов решения проблемы — создание в классе

SortCount

сеттеров

setSORTNAME

и

setCOUNTOFSORT

, а другим — использование методов

addScalar

с явным указанием названий (и типов) полей результата запроса. Второй вариант ликвидирует разногласие между метаданными СУБД и правилом наименования методов в

Java

, а также быстрее работает.

Вызов хранимой функции базы данных Oracle

Задача. В базе данных есть хранимая процедура (функция)

GETPOSITION

, которая принимает id группы деревьев сада в качестве аргумента и в качестве результата возвращает

место этой группы среди всех по количеству деревьев в ней. Получить результат работы такой хранимой

процедуры базы данных Oracle.

Решение. Функция принимает в качестве параметра и возвращает значение целочисленного типа.

SQL-запрос для получения результата имеет такой вид:

SELECT GETPOSITION(12) FROM DUAL;

Точку с запятой нужно опустить, а число 12 заменить на целочисленную переменную, которая содержит

id

некоторой группы деревьев. Также обязательно добавить алиас, иначе СУБД сгенерирует свой

(Oracle, например, так и назовет поле —

GETPOSITION(12))

, акцессоры для которого часто просто невозможно создать. Результат запроса можно поместить в

любой класс, в котором есть свойство с именем алиаса.

Назовем алиас

position

и создадим класс

Position

:

public class Position {
private int position;

public int getPosition() {
return position;
}

public void setPosition(int position) {
this.position = position;
}
}

В данном случае результат работы функции можно получить таким образом:

int group = 25;

Position position = (Position) session.createSQLQuery("select getposition("+group+") position from dual").addScalar

("position", Hibernate.INTEGER).setResultTransformer(Transformers.aliasToBean(Position.class)).uniqueResult();

Результат будет помещен в переменную

position

. Ничего нового в этом коде нет, разве что метод

uniqueResult()

, который возвращает не список значений, ка метод

list()

, а одно значение.

Выводы

HIBERNATE — довольно гибкий фреймворк, он позволяет многие действия произвести разными способами. Например, запрос на выборку можно осуществить с помощью HQL, Criteria и Native SQL. Тот или иной выбор зависит скорее от личных предпочтений разработчика, но в ряде случаев без использования родного языка запросов СУБД не обойтись. Это справедливо в первую очередь для СУБД с развитыми процедурными расширениями SQL: Oracle, MS SQL Server, IBM DB2.

 
 
След. »
Взаимосвязанные статьи
     

Последние добавленные статьи
Поиск
Ссылки
Главная
Скачать
Курсы
Роль АБД (SYSDBA)
Карта сайта
Автостекла
Контакты
Войти на сайт
Популярные статьи
Online - тесты
1Z0-042
Rambler's Top100 МЕТА - Украина. Рейтинг сайтов хостинг от freehost.com.ua

Все права защищены.SYSDBA 2010 | Если у Вас есть хороший материал пришлите его нам.