hibernate第三天——session的快取與事務隔離級別,一對一關係,多種方式查詢
package cn.itcast.k_query_hql; import java.util.Arrays; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.Test; public class App { private static SessionFactory sessionFactory = new Configuration()// .configure()// .addClass(Department.class)// 新增Hibernate實體類(載入對應的對映檔案) .addClass(Employee.class)// 新增Hibernate實體類(載入對應的對映檔案) .buildSessionFactory(); // 準備資料 @Test public void testSave() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 儲存一些部門資料 for (int i = 1; i <= 10; i++) { Department department = new Department(); department.setName("開發部_" + i); session.save(department); } // 儲存一些員工資料 for (int i = 1; i <= 20; i++) { Employee employee = new Employee(); employee.setName("李XX_" + i); session.save(employee); } // -------------------------------------------- session.getTransaction().commit(); session.close(); } // 使用HQL查詢 // HQL: Hibernate Query Language. // 特點: // >> 1,與SQL相似,SQL中的語法基本上都可以直接使用。 // >> 2,SQL查詢的是表和表中的列;HQL查詢的是物件與物件中的屬性。 // >> 3,HQL的關鍵字不區分大小寫,類名與屬性名是區分大小寫的。 // >> 4,SELECT可以省略. @Test public void testHql() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- String hql = null; // 1,簡單的查詢 // hql = "FROM Employee"; // hql = "FROM Employee AS e"; // 使用別名 // hql = "FROM Employee e"; // 使用別名,as關鍵字可省略。別名用來防止關鍵字衝突,推薦使用別名 // 2,帶上過濾條件的(可以使用別名):Where // hql = "FROM Employee WHERE id<10"; // hql = "FROM Employee e WHERE e.id<10"; // hql = "FROM Employee e WHERE e.id<10 AND e.id>5"; // 3,帶上排序條件的:Order By // hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name"; // hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC"; // hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC, id ASC"; // 4,指定select子句(不可以使用select *) // hql = "SELECT e FROM Employee e"; // 相當於"FROM Employee e" // hql = "SELECT e.name FROM Employee e"; // 只查詢一個列,返回的集合的元素型別就是這個屬性的型別 // hql = "SELECT e.id,e.name FROM Employee e"; // 查詢多個列,返回的集合的元素型別是Object陣列 // hql = "SELECT new Employee(e.id,e.name) FROM Employee e"; // 可以使用new語法,指定把查詢出的部分屬性封裝到物件中 // 5,執行查詢,獲得結果(list、uniqueResult、分頁 ) // Query query = session.createQuery("FROM Employee e WHERE id<3"); // query.setFirstResult(0); // query.setMaxResults(10); // // List list = query.list(); // 查詢的結果是一個List集合 // Employee employee = (Employee) query.uniqueResult();// 查詢的結果是唯一的一個結果,當結果有多個,就會拋異常 // System.out.println(employee); // 6,方法鏈 List list = session.createQuery(// "FROM Employee")// .setFirstResult(0)// .setMaxResults(10)// .list(); // // ----- 執行查詢 // List list = session.createQuery(hql).list(); // // ----- 顯示結果 for (Object obj : list) { if (obj.getClass().isArray()) { System.out.println(Arrays.toString((Object[]) obj)); } else { System.out.println(obj); } } // -------------------------------------------- session.getTransaction().commit(); session.close(); } @Test public void testHql_2() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- String hql = null; // 1,聚集函式:count(), max(), min(), avg(), sum() // hql = "SELECT COUNT(*) FROM Employee"; // 返回的結果是Long型的 // hql = "SELECT min(id) FROM Employee"; // 返回的結果是id屬性的型別 // Number result = (Number) session.createQuery(hql).uniqueResult(); // System.out.println(result.getClass()); // System.out.println(result); // 2,分組: Group By ... Having // hql = "SELECT e.name,COUNT(e.id) FROM Employee e GROUP BY e.name"; // hql = "SELECT e.name,COUNT(e.id) FROM Employee e GROUP BY e.name HAVING count(e.id)>1"; // hql = "SELECT e.name,COUNT(e.id) FROM Employee e WHERE id<9 GROUP BY e.name HAVING count(e.id)>1"; // --- // hql = "SELECT e.name,COUNT(e.id) " + // // "FROM Employee e " + // // "WHERE id<9 " + // // "GROUP BY e.name " + // // "HAVING count(e.id)>1 " + // // "ORDER BY count(e.id) ASC"; // --- // hql = "SELECT e.name,COUNT(e.id) AS c " + // // "FROM Employee e " + // // "WHERE id<9 " + // // "GROUP BY e.name " + // // "HAVING count(e.id)>1 " + // 在having子句中不能使用列別名 // "ORDER BY c ASC"; // 在orderby子句中可以使用列別名 // 3,連線查詢 / HQL是面向物件的查詢 // >> 內連線(inner關鍵字可以省略) // hql = "SELECT e.id,e.name,d.name FROM Employee e JOIN e.department d"; // hql = "SELECT e.id,e.name,d.name FROM Employee e INNER JOIN e.department d"; // >> 左外連線(outer關鍵字可以省略) // hql = "SELECT e.id,e.name,d.name FROM Employee e LEFT OUTER JOIN e.department d"; // >> 右外連線(outer關鍵字可以省略) // hql = "SELECT e.id,e.name,d.name FROM Employee e RIGHT JOIN e.department d"; // 可以使用更方便的方法 // hql = "SELECT e.id,e.name,e.department.name FROM Employee e"; // 4,查詢時使用引數 // >> 方式一:使用'?'佔位 // hql = "FROM Employee e WHERE id BETWEEN ? AND ?"; // List list = session.createQuery(hql)// // .setParameter(0, 5)// 設定引數,第1個引數的索引為0。 // .setParameter(1, 15)// // .list(); // >> 方式二:使用變數名 // hql = "FROM Employee e WHERE id BETWEEN :idMin AND :idMax"; // List list = session.createQuery(hql)// // .setParameter("idMax", 15)// // .setParameter("idMin", 5)// // .list(); // 當引數是集合時,一定要使用setParameterList()設定引數值 // hql = "FROM Employee e WHERE id IN (:ids)"; // List list = session.createQuery(hql)// // .setParameterList("ids", new Object[] { 1, 2, 3, 5, 8, 100 })// // .list(); // 5,使用命名查詢 // Query query = session.getNamedQuery("queryByIdRange"); // query.setParameter("idMin", 3); // query.setParameter("idMax", 10); // List list = query.list(); // 6,update與delete,不會通知Session快取 // >> Update // int result = session.createQuery(// // "UPDATE Employee e SET e.name=? WHERE id>15")// // .setParameter(0, "無名氏")// // .executeUpdate(); // 返回int型的結果,表示影響了多少行。 // System.out.println("result = " + result); // >> Delete int result = session.createQuery(// "DELETE FROM Employee e WHERE id>15")// .executeUpdate(); // 返回int型的結果,表示影響了多少行。 System.out.println("result = " + result); // ----- 執行查詢並顯示結果 // // List list = session.createQuery(hql).list(); // for (Object obj : list) { // if (obj.getClass().isArray()) { // System.out.println(Arrays.toString((Object[]) obj)); // } else { // System.out.println(obj); // } // } // -------------------------------------------- session.getTransaction().commit(); session.close(); } @Test public void testHql_DML() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 第一次顯示名稱 Employee employee = (Employee) session.get(Employee.class, 13); System.out.println(employee.getName()); // update與delete,不會通知Session快取 int result = session.createQuery(// "UPDATE Employee e SET e.name=? WHERE id>10")// .setParameter(0, "無名氏3")// .executeUpdate(); // 返回int型的結果,表示影響了多少行。 // 第二次顯示名稱 // 在update或delete後,需要refresh(obj)一下以獲取最新的狀態 session.refresh(employee); System.out.println(employee.getName()); // -------------------------------------------- session.getTransaction().commit(); session.close(); } }
5、多種查詢方式——qbc
package cn.itcast.k_query_qbc; import java.util.Arrays; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.junit.Test; public class App { private static SessionFactory sessionFactory = new Configuration()// .configure()// .addClass(Department.class)// 新增Hibernate實體類(載入對應的對映檔案) .addClass(Employee.class)// 新增Hibernate實體類(載入對應的對映檔案) .buildSessionFactory(); // 準備資料 @Test public void testSave() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 儲存一些部門資料 for (int i = 1; i <= 10; i++) { Department department = new Department(); department.setName("開發部_" + i); session.save(department); } // 儲存一些員工資料 for (int i = 1; i <= 20; i++) { Employee employee = new Employee(); employee.setName("李XX_" + i); session.save(employee); } // -------------------------------------------- session.getTransaction().commit(); session.close(); } // 使用QBC方式查詢:Query By Criteria @Test public void testQBC() throws Exception { Session session = sessionFactory.openSession(); session.beginTransaction(); // -------------------------------------------- // 建立Criteria物件 Criteria criteria = session.createCriteria(Employee.class); // 增加過濾條件 criteria.add(Restrictions.ge("id", 1)); criteria.add(Restrictions.le("id", 5)); // 增加排序條件 criteria.addOrder(Order.desc("name")); criteria.addOrder(Order.desc("id")); // 執行查詢 // criteria.setFirstResult(0); // criteria.setMaxResults(100); // criteria.uniqueResult(); // criteria.list() List list = criteria.list(); // 顯示結果 for (Object obj : list) { if (obj.getClass().isArray()) { System.out.println(Arrays.toString((Object[]) obj)); } else { System.out.println(obj); } } // -------------------------------------------- session.getTransaction().commit(); session.close(); } }
一、一對一的關聯關係對映(外來鍵 + 唯一)
基於外來鍵的
有外來鍵方:<many-to-one name="obj" class=".." column=".." unique="true"/>
無外來鍵方:<one-to-one name=".." class=".." property-ref="obj"/>
基於主鍵的
有外來鍵方:<one-to-one ...>
無外來鍵方:<one-to-one ...>
操作:
在採用基於外來鍵的方式時:只有有外來鍵方可以維護關聯關係。
在採用基於主鍵的方式時:雙方都不可以維護關係。
二、繼承結構對映
1,整個繼承結構使用一張表。列上不能有not-null="true"。
2,每個類對應一張表,抽象類也對應表。
3,每個具體類對應一張表,抽象類不對應表。
三、HQL語句
與SQL的語法類似。
HQL查詢的物件、屬性,所以寫的時候寫的是類名、屬性名。
HQL的關鍵字不區分大小寫,類名與屬性名區分大小寫。
語法:
SELECT 別名/屬性名/表示式
FROM 實體 AS 別名
WHERE 過濾條件
ORDER BY 排序條件
SELECT 別名/屬性名/表示式
FROM 實體 AS 別名
WHERE 過濾條件
GROUP BY 分組條件
HAVING 分組後的結果的過濾條件
ORDER BY 排序條件