Java hibernate sql запросы

Чтение объектов в Hibernate

Извлечение информации из базы данных в виде коллекции объектов Hibernate может выполнять с использованием :

HQL Hibernate Query Language;
SQL native SQL query;
Criteria Hibernate Criteria API.

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

Чтение данных с использованием HQL

Hibernate может использовать свой мощный язык запросов Hibernate Query Language, который очень похож на родной SQL. В сравнении с SQL, HQL полностью объектно-ориентирован и использует понятия наследования, полиформизма и связывания. Подробное описание языка HQL будет представлено в ближайшие дни.

Следующий метод демонстрирует чтение набора данных пользователей User. HQL запрос формируется с использованием наименования класса. После этого создается запрос Query методом createQuery(sql) объекта сессии и извлекаются данные методом list ().

private void readUsers_HQL() < System.out.println("\n\nЧтение записей : HQL"); // HQL (Hibernate Query Language) String sql = "From " + User.class.getSimpleName(); System.out.println("sql = " + sql); Listusers = session.createQuery(sql).list(); System.out.println("users.size = " + users.size()); for (Iterator it = users.iterator(); it.hasNext();) < User user = (User) it.next(); System.out.println(user.toString()); >>

Запросы Hibernate и данные выводятся в консоль (см. ниже). Обратите внимание, что при создании запроса Query методом createQuery(sql) Hibernate формирует соответствующий запрос чтения списка пользователей. Второй запрос по чтению связанных записей Auto формируется и выполняется уже при распечатке пользователя, т.е. при обращении к связанной сущности (lazy загрузка).

Чтение записей : HQL sql = From User Hibernate: select user0_.id as id1_0_, user0_.login as login2_0_, user0_.name as name3_0_ from USERS user0_ users.size = 2 Hibernate: select autos0_.user_id as user_id3_0_0_, autos0_.aid as aid1_1_0_, autos0_.aid as aid1_1_1_, autos0_.name as name2_1_1_, autos0_.user_id as user_id3_1_1_ from autos autos0_ where autos0_.user_id=? User , Auto ]> User

Чтение данных с использованием native SQL-запроса

Hibernate позволяет выполнять native SQL-запросы с использованием org.hibernate.SQLQuery, который создается методом createSQLQuery(String) объекта сессии. Но необходимо учитывать, что в этом случае можно потерять все преимущества HQL (ассоциации, кэширование). Следующий код демонстрирует использование нативного запроса для получения коллекции пользователей.

private void readUsers_SQL() < System.out.println("\n\nЧтение записей : SQL"); // Использование native SQL query String sql = "select ID, LOGIN, NAME from USERS"; Query query = session.createSQLQuery(sql).addEntity(User.class); Listusers = query.list(); System.out.println("users.size = " + users.size()); for (Iterator it = users.iterator(); it.hasNext();) < User user = (User) it.next(); System.out.println(user.toString()); >>

При формировании объекта Query был добавлен класс User.class методом addEntity, в результате чего метод list объекта Query вернул коллекцию пользователей List. Объект org.hibernate.SQLQuery расширяет возможности двух классов org.hibernate.Query, org.hibernate.SynchronizeableQuery и является потокобезопасным.

Набор прочитанных данных выводится в консоль, представленную ниже. Обратите внимание, что также, как и для HQL, при использовании native SQL второй запрос чтения связанных сущностей формируется по мере необходимости, т.е. при обращении.

Чтение записей : SQL Hibernate: select ID, LOGIN, NAME from USERS users.size = 2 Hibernate: select autos0_.user_id as user_id3_0_0_, \ autos0_.aid as aid1_1_0_, \ autos0_.aid as aid1_1_1_, \ autos0_.name as name2_1_1_, \ autos0_.user_id as user_id3_1_1_ \ from autos autos0_ where autos0_.user_id=? User , Auto ]> User
Чтение набора объектов, List

Читайте также:  Include controller php failed to open stream no such file or directory in

При выполнении сложных нативных SQL-запросов для извлечения определенной информации можно сущности к объекту org.hibernate.Query не подключать. В этом случае метод list() объекта Query вернет коллекцию объектов List, как это показано в следующем коде. После этого список объектов можно парсить и использовать по назначению.

private void readObjects() < System.out.println("\n\nЧтение объектов"); String sql = "select ID, LOGIN, NAME from USERS"; Query query = session.createSQLQuery(sql); Listrows = query.list(); for(Object[] row : rows) < User user = new User(); user.setId (Integer.valueOf(row[0].toString())); user.setLogin (row[1].toString()); user.setName (row[2].toString()); System.out.println(user.toString()); >>

В результате выполнения метода readObjects() в консоль будет выведена информация без подгрузки связанных сущностей Auto :

Чтение объектов Hibernate: select ID, LOGIN, NAME from USERS User User

Использование org.hibernate.Criteria

Интерфейс org.hibernate.Criteria представляет собой объектно-ориентированный запрос на выборку в отношении конкретной сущности и позволяет выполнять запросы без написания SQL кода. Для создания экземпляров Criteria используется класс Session, который выступает в качестве фабрики.

Следующий метод выполняет чтение списка пользователей с именем «Иван». При создании Criteria используется метод createCriteria объекта сессии Session, которому в качестве параметра передается класс объекта. Объект criteria имеет метод add, позволяющий выполнить фильтрацию данных. Для этого методу add необходимо передать параметр ограничения Restrictions с определенными условиями.

private void readUsers_criteria() < System.out.println("\n\nCriteria API"); Criteria criteria; criteria = session.createCriteria(User.class) .add(Restrictions.eq("name", "Иван")); Listusers = criteria.list(); for (Iterator it = users.iterator(); it.hasNext();) < User user = (User) it.next(); System.out.println(user.toString()); >>

Результат выполнения метода readUsers_criteria выведен в консоль :

Criteria API Hibernate: select this_.id as id1_0_0_, \ this_.login as login2_0_0_, \ this_.name as name3_0_0_ \ from USERS this_ \ where this_.name=? Hibernate: select autos0_.user_id as user_id3_0_0_, \ autos0_.aid as aid1_1_0_, \ autos0_.aid as aid1_1_1_, \ autos0_.name as name2_1_1_, \ autos0_.user_id as user_id3_1_1_ from autos autos0_ where autos0_.user_id=? User , Auto ]>

Подробное описание org.hibernate.Criteria с примерами представлено здесь.

Фильтрация данных в Hibernate

Для чтения данных с фильтрацией можно использовать как org.hibernate.Criteria, представленный выше, так и native SQL. Метод readUsers демонстрирует извлечение отдельной записи пользователя, у которой логин соответствует значению параметра метода «filter» :

private void readUsers(final String filter) < String sql; // Использование native SQL query с условием sql = "select ID, LOGIN, NAME from USERS where login like :log"; Query query = session.createSQLQuery (sql) // SQL .addEntity (User.class) // Class .setParameter ("log", filter); // Condition Listusers = query.list(); System.out.println("users.size = " + users.size()); for (Iterator it = users.iterator(); it.hasNext();) < User user = (User) it.next(); System.out.println(user.toString()); >>

При создании объекта SQLQuery (native SQL) была добавлена сущность (addEntity) и определен параметр «log» (setParameter). В консоли увидим следующую информацию :

Hibernate: select ID, LOGIN, NAME from USERS where login like ? users.size = 1 User , Auto ]>

Чтение отдельной записи

Если известен идентификатор сущности Id, то объект сессии Session позволяет прочитать запись. Для этого можно использовать метод get или load. Отличия методов get и load представлено на странице Hibernate в вопросах и ответах. Следующий код демонстрирует чтение записи пользователя с идентификатором :

User user = (User) session.load(User.class, 51); if (user != null) System.out.println("\n\n" + user.toString());

Скачать пример

Исходный код рассмотренного на странице примера использования различных способов Hibernate для чтения данных в виде проекта Eclipse, включающий все необходимые библиотеки hibernate, можно скачать здесь (8.02 Mб).

Источник

Hibernate для самых маленьких и не только

Доброго всем времени суток! При написании программы, которая так или иначе будет взаимодействовать с базой данных, пользуются разными средствами. Это и старый добрый jdbc, также применяют: EclipseLink,TopLink, iBatis (уже MyBatis), Spring Framework и конечно же герой нашей статьи — Hibernate. Конечно я здесь перечислил не все средства работы с базой данных, но постарался указать самые распространенные. В данной статье будет показано, как при помощи Hibernate вызывать хранимые процедуры, маппить как таблицы, так и запросы к классам. В качестве подопытной базы данных возьмем Oracle.
Подготовим все необходимое для экспериментов. Начнем с базы данных. Для начала создадим 3 таблички, над которыми мы и будем практиковаться.

CREATE TABLE book ( id NUMBER NOT NULL, name VARCHAR2 (100 BYTE) NOT NULL, description VARCHAR2 (1000 BYTE) NOT NULL, CONSTRAINT pk$book_id PRIMARY KEY (id) ) CREATE TABLE student ( id NUMBER NOT NULL, name VARCHAR2 (100 BYTE) NOT NULL, CONSTRAINT pk$student_id PRIMARY KEY (id) ) CREATE TABLE catalog ( id_student NUMBER NOT NULL, id_book NUMBER NOT NULL ) 

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

CREATE OR REPLACE FUNCTION get_book_name_by_id (p_id IN NUMBER) RETURN VARCHAR2 IS v_name VARCHAR2 (100); BEGIN SELECT name INTO v_name FROM book WHERE RETURN v_name; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 'ну нет такой книги!!'; END; 

И также в качестве эксперимента создадим простую процедуру сохранения в БД, у которой будут как входные параметры, так и выходной.

CREATE OR REPLACE PROCEDURE save_book (p_id IN OUT NUMBER, p_name IN VARCHAR2, p_descr IN VARCHAR2) IS BEGIN IF p_id > 0 THEN UPDATE book SET name = p_name, description = p_descr WHERE ELSE SELECT catalog_seq.NEXTVAL INTO p_id FROM DUAL; INSERT INTO book VALUES (p_id, p_name, p_descr); END IF; END; 
@Entity @Table public class Student implements Serializable < private static final long serialVersionUID = -5170875020617735653L; @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen") @SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "catalog_seq") private long id; @Column private String name; @OneToMany(mappedBy = "student", fetch = FetchType.LAZY) private SetbookList; // здесь идет реализация методов getter, setter, hashCode(), equals(), toString() > 
  • если у вас название класса не совпадает с названием таблицы, то например пишем так: Table(name = «STUDENT»);
  • одно из требований фреймворка — у каждой таблицы должен быть id, также если название поля id таблицы и название нашей переменной не совпадают, тогда аннотация будет выглядить так: Id @Column(name=«id таблицы в базе»);
  • аннотациями @GeneratedValue и @SequenceGenerator мы определяем стратегию генерации уникального идентификатора, в данном случае мы говорим, что при сохранении информации в базу данных, мы берем число из sequence с названием «catalog_seq»;
  • так как у нас один студент может иметь несколько книг, то отобразим это при помощи аннотации таким образом @OneToMany(mappedBy = «student», fetch = FetchType.LAZY), где mappedBy = «student» — это имя поля в классе Book(смотри ниже), а FetchType.LAZY — говорит нам о том, что коллекцию
@Entity @Table public class Book implements Serializable < private static final long serialVersionUID = 1L; @Id @Column(name="ID") @GeneratedValue(strategy = GenerationType.AUTO, generator = "my_entity_seq_gen") @SequenceGenerator(name = "my_entity_seq_gen", sequenceName = "catalog_seq") private long id; @Column(name="NAME",unique = true, nullable = false, length = 100) private String name; @Column(name="DESCRIPTION",unique = true, nullable = false, length = 100) private String description; @ManyToOne(fetch = FetchType.LAZY,optional=true) @JoinTable(name = "CATALOG", joinColumns = @JoinColumn(name = "ID_BOOK"), inverseJoinColumns = @JoinColumn(name = "ID_STUDENT")) private Student student; // здесь идет реализация методов getter, setter, hashCode(), equals(), toString() >
 List book = (List)session.createQuery("from Book order by name").list(); 
 List book = (List)session.createSQLQuery("select ID, DESCRIPTION, NAME from book order by NAME") .addScalar("id",Hibernate.LONG).addScalar("name").addScalar("description") .setResultTransformer(Transformers.aliasToBean(Book.class)).list(); 
 List book=(List)session.createCriteria(Book.class).createAlias("student", "st").add(Restrictions.eq("st.name", "Maxim")).list(); 
String bookName = (String)session.createSQLQuery("").setLong("id",1).uniqueResult(); 

Допустим у нас на сервере нет таблицы с названием Student, а есть только функция, которая возвращает курсор:

FUNCTION get_all_students RETURN SYS_REFCURSOR IS l_cur SYS_REFCURSOR; BEGIN OPEN l_cur FOR SELECT * FROM student ORDER BY 1; RETURN l_cur; END; 
@NamedNativeQuery(name="getAllStudent",query="", callable=true, resultClass=Student.class)
 List student = (List) session.getNamedQuery("entity").list();
CallableStatement st = session.connection().prepareCall(""); st.setLong(1,0); st.setString(2, "Золотой ключик, или Приключения Буратино"); st.setString(3,"повесть-сказка Алексея Николаевича Толстого"); st.registerOutParameter(1, java.sql.Types.NUMERIC); st.execute(); System.out.println(st.getLong(1)); 

Как Вы наверно успели заметить, при написании команд для обращения к базе данных и заполнением коллекции, использовалось слово session. В нашем случае это слово указывает на главный интерфейс между нашим Java-приложением и фреймворком Hibernate, то есть org.hibernate.Session session. Но для начала нам необходимо воспользоваться еще одним основополагающим и важным интерфейсом — SessionFactory. SessionFactory — это глобальная фабрика, ответственная за конкретную базу данных. Чтобы получить эту фабрику нам необходимо получить экземпляр класса org.hibernate.cfg.Configuration. Делается это так:

 SessionFactory sessions = new Configuration().configure().buildSessionFactory(); 

Где Configuration().configure().buildSessionFactory() парсит файлик с названием hibernate.cfg.xml, который находится рядом с вызываемой программой, конечно если не указан путь. Приведем файл конфигурации, в котором показана настройка соединения к базе данных и отображение наших таблиц:

     oracle.jdbc.driver.OracleDriver jdbc:oracle:thin:@localhost:port:baseName username password org.hibernate.dialect.Oracle10gDialect true   

И теперь, когда мы имеем фабрику, в которой есть вся необходимая конфигурация (коннект к базе через пул, маппинг/отображение таблиц и др.) мы можем работать с Session

Session session = sessions.openSession();

Работать с транзакциями можно так: session.beginTransaction(); и соответственно session.getTransaction().commit();
Вроде бы все. Конечно я не все смог осветить, но думаю для быстрого старта этого хватит.

Источник

Оцените статью