הדרכה לדוגמאות בקריטריונים של Hibernate

ברוכים הבאים למדריך לדוגמא של השתייכות. היום נבחן קריטריונים ב־היברנייט.

קריטריונים של היברנייט

לרוב, אנו משתמשים ב־HQL לשאילתת מסד הנתונים ולקבלת התוצאות. HQL אינה הדרך המועדפת לעדכון או למחיקת ערכים מאחר ואז עלינו לטפל באיזוריות בין הטבלאות. API של קריטריונים של היברנייט מספק גישה מבוססת אובייקט לשאילתת מסד הנתונים ולקבלת התוצאות. אין לנו אפשרות להשתמש בקריטריונים של היברנייט כדי להריץ שאילתות עדכון או מחיקה או כל הצהרות DDL כלשהן. שאילתת קריטריונים של היברנייט משמשת רק לקבלת התוצאות ממסד הנתונים באמצעות גישה מבוססת אובייקט. עבור דוגמת הקריטריונים שלי ב־Hibernate, אשתמש באותה ההתקנה כמו ב־דוגמת HQL שלי ואראה לך כיצד להשתמש בקריטריונים של היברנייט לשאילתת מסדי נתונים. כמה מהשימושים הנפוצים בAPI של קריטריונים של היברנייט הם;

  1. API של קריטריונים של היברנייט מספק תקנות שאנו יכולים להשתמש בהן עבור פונקציות כוללות כמו סכום(), מינימום(), מקסימום() וכו'.
  2. API של קריטריונים של היברנייט יכול להשתמש עם ProjectionList כדי לקבל עמודות שנבחרו בלבד.
  3. קריטריונים ב-Hibernate ניתן להשתמש בהם לשאילתות הצטרפות על ידי שילוב רבות של טבלאות, שיטות שימושיות לכך ב-Hibernate criteria הן createAlias(), setFetchMode() ו-setProjection()
  4. קריטריונים ב-API של Hibernate ניתן להשתמש בהם לקבלת תוצאות עם תנאים, שיטות שימושיות הן add() בה נוכל להוסיף אילוצים.
  5. API של Hibernate Criteria מספקת את השיטה addOrder() שבאמצעותה ניתן לסדר את התוצאות.

במחלקה למטה מוצגים שימושים שונים של API של Hibernate Criteria, רובם הם החלפות לדוגמאות במדריך של HQL.

package com.journaldev.hibernate.main;

import java.util.Arrays;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;

public class HibernateCriteriaExamples {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		// הכנה מראש
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.getCurrentSession();
		Transaction tx = session.beginTransaction();

		//קבלת כל העובדים
		Criteria criteria = session.createCriteria(Employee.class);
		List empList = criteria.list();
		for(Employee emp : empList){
			System.out.println("ID="+emp.getId()+", Zipcode="+emp.getAddress().getZipcode());
		}
		
		// קבלה לפי זיהוי, יצירת Criteria חדשה להסרת כל הגדרות
		criteria = session.createCriteria(Employee.class)
					.add(Restrictions.eq("id", new Long(3)));
		Employee emp = (Employee) criteria.uniqueResult();
		System.out.println("Name=" + emp.getName() + ", City="
				+ emp.getAddress().getCity());

		//דוגמא לדפוס
		empList = session.createCriteria(Employee.class)
					.addOrder(Order.desc("id"))
					.setFirstResult(0)
					.setMaxResults(2)
					.list();
		for(Employee emp4 : empList){
			System.out.println("Paginated Employees::"+emp4.getId()+","+emp4.getAddress().getCity());
		}

		//דוגמא עבור like
		empList = session.createCriteria(Employee.class)
				.add(Restrictions.like("name", "%i%"))
				.list();
		for(Employee emp4 : empList){
			System.out.println("Employees having 'i' in name::"+emp4.getName()+","+emp4.getAddress().getCity());
		}
		
		//דוגמא עבור פרויקציות
		long count = (Long) session.createCriteria(Employee.class)
				.setProjection(Projections.rowCount())
				.add(Restrictions.like("name", "%i%"))
				.uniqueResult();
		System.out.println("Number of employees with 'i' in name="+count);

		//שימוש בפרויקציות עבור פונקציות כגון סכום, מינימום, מקסימום
		double sumSalary = (Double) session.createCriteria(Employee.class)
			.setProjection(Projections.sum("salary"))
			.uniqueResult();
		System.out.println("Sum of Salaries="+sumSalary);
		
		//דוגמא להצטרפות לבחירת כמה עמודות
		criteria = session.createCriteria(Employee.class, "employee");
		criteria.setFetchMode("employee.address", FetchMode.JOIN);
		criteria.createAlias("employee.address", "address"); // inner join by default

		ProjectionList columns = Projections.projectionList()
						.add(Projections.property("name"))
						.add(Projections.property("address.city"));
		criteria.setProjection(columns);

		List list = criteria.list();
		for(Object[] arr : list){
			System.out.println(Arrays.toString(arr));
		}
		
		
		// ביטול עסקה כדי למנוע אי סדר בנתוני הבדיקה
		tx.commit();
		// סגירת משאבי Hibernate
		sessionFactory.close();
	}

}

כאשר אנו מפעילים את דוגמת ה-Hibernate Criteria לעיל, אנו מקבלים את הפלט הבא.

May 26, 2014 6:53:32 PM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
May 26, 2014 6:53:32 PM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.5.Final}
May 26, 2014 6:53:32 PM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
May 26, 2014 6:53:32 PM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
May 26, 2014 6:53:32 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: hibernate.cfg.xml
May 26, 2014 6:53:32 PM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: hibernate.cfg.xml
May 26, 2014 6:53:32 PM org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
WARN: HHH000223: Recognized obsolete hibernate namespace https://hibernate.sourceforge.net/. Use namespace https://www.hibernate.org/dtd/ instead. Refer to Hibernate 3.6 Migration Guide!
May 26, 2014 6:53:32 PM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
Hibernate Configuration loaded
Hibernate serviceRegistry created
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/TestDB]
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=pankaj, password=****}
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
May 26, 2014 6:53:32 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
May 26, 2014 6:53:32 PM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
May 26, 2014 6:53:32 PM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id
ID=1, Zipcode=95129
ID=2, Zipcode=95051
ID=3, Zipcode=560100
ID=4, Zipcode=100100
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id where this_.emp_id=?
Name=Lisa, City=Bangalore
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id order by this_.emp_id desc limit ?
Paginated Employees::4,New Delhi
Paginated Employees::3,Bangalore
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id where this_.emp_name like ?
Employees having 'i' in name::David,Santa Clara
Employees having 'i' in name::Lisa,Bangalore
Hibernate: select count(*) as y0_ from EMPLOYEE this_ where this_.emp_name like ?
Number of employees with 'i' in name=2
Hibernate: select sum(this_.emp_salary) as y0_ from EMPLOYEE this_
Sum of Salaries=1000.0
Hibernate: select this_.emp_name as y0_, address1_.city as y1_ from EMPLOYEE this_ inner join ADDRESS address1_ on this_.emp_id=address1_.emp_id
[Pankaj, San Jose]
[David, Santa Clara]
[Lisa, Bangalore]
[Jack, New Delhi]
May 26, 2014 6:53:32 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://localhost/TestDB]

מכיוון שאני משתמש בפרויקט דוגמא של HQL, יידרוש ממך לייבא את זה ולאחר מכן להוסיף מחלקה זו כדי שהכל יעבוד. שים לב לשאילתות ה-Hibernate שמתבצעות בפלט, ובכך תוכל למקם את שאילתותיך ולקבל את התוצאות שאתה מחפש. זהו כל הדברים לסיכום מהיר על קריטריונים ב-Hibernate.

Source:
https://www.digitalocean.com/community/tutorials/hibernate-criteria-example-tutorial