通過hibernate進行數據的查詢,一般會采用HQL語句,HQL是將數據表對象化的查詢語言,和SQL類似,但卻是通過面向對象的方式去書寫,更易于理解。寫一個測試類,將一般情況下會用到的HQL寫法記錄下來。
1 package demo; 2 3 import java.util.List; 4 5 import org.hibernate.Query; 6 import org.hibernate.Session; 7 import org.junit.Test; 8 9 import domain.Classroom; 10 import domain.ReportDto; 11 import domain.Specialty; 12 import domain.Student; 13 import util.HibernateUtil; 14 15 16 public class App 17 { 18 19 @SuppressWarnings("unchecked") 20 @Test 21 public void hqltest01(){ 22 Session session = null; 23 try { 24 session = HibernateUtil.openSession(); 25 session.beginTransaction(); 26 //全查詢
27 Query q = session.createQuery("from Student"); 28 List<Student> ss = q.list(); 29 for (Student s : ss) { 30 System.out.println(s.getName()); 31 } 32 33 System.err.println("================================="); 34 35 //條件查詢
36 Query q1 = session.createQuery("from Student s where s.name like ?") 37 .setParameter(0, "%小%"); 38 //還可以基于參數名的方式,比如hql中為:name,則setParameter("name", "%小%")
39 List<Student> sss = q1.list(); 40 for (Student s : sss) { 41 System.out.println(s.getName()); 42 } 43 44 session.getTransaction().commit(); 45 46 } catch (Exception e) { 47 if (session != null) { 48 session.getTransaction().rollback(); 49 } 50 } finally{ 51 if (session != null) { 52 session.close(); 53 } 54 } 55 } 56 57 @Test 58 /**
59 * 查詢唯一結果
60 */ 61 public void hqltest02(){ 62 Session session = null; 63 try { 64 session = HibernateUtil.openSession(); 65 session.beginTransaction(); 66 67 //查詢記錄的數量
68 Query q = session.createQuery("select count(*) from Student"); 69 Long l = (Long) q.uniqueResult(); 70 System.out.println(l); 71 72 //查詢某個特定對象
73 Query q1 = session.createQuery("from Student s where s.id = 1"); 74 Student s = (Student) q1.uniqueResult(); 75 System.out.println(s.getName()); 76 session.getTransaction().commit(); 77 78 } catch (Exception e) { 79 if (session != null) { 80 session.getTransaction().rollback(); 81 } 82 } finally{ 83 if (session != null) { 84 session.close(); 85 } 86 } 87 } 88 89 @SuppressWarnings("unchecked") 90 @Test 91 /**
92 * 查詢一個投影
93 */ 94 public void hqltest03(){ 95 Session session = null; 96 try { 97 session = HibernateUtil.openSession(); 98 session.beginTransaction(); 99 100 //查詢記錄的數量
101 Query q = session.createQuery("select s.grade,count(*) from Student s group by s.grade");102 List<Object[]> objs = q.list();103 for (Object[] obj : objs) {104 System.out.println(obj[0]+":"+obj[1]);105 }106 107 } catch (Exception e) {108 if (session != null) {109 session.getTransaction().rollback();110 }111 } finally{112 if (session != null) {113 session.close();114 }115 }116 }117 118 @SuppressWarnings("unchecked")119 @Test120 /**
121 * 基于導航對象進行,傳統sql語句進行跨表查詢時,需要進行連接
122 * hql提供了導航查詢.
123 * *但是不建議使用導航查詢,導航查詢使用cross join進行查詢,低效
124 */125 public void hqltest04(){126 Session session = null;127 try {128 session = HibernateUtil.openSession();129 session.beginTransaction();130 131 //查詢記錄的數量
132 Query q = session.createQuery("from Student s where s.classroom.id = 1");133 List<Student> ss = q.list();134 for (Student s : ss) {135 System.out.println(s.getName());136 }137 138 } catch (Exception e) {139 if (session != null) {140 session.getTransaction().rollback();141 }142 } finally{143 if (session != null) {144 session.close();145 }146 }147 }148 149 @SuppressWarnings("unchecked")150 @Test151 /**
152 * 參數列表的設置
153 */154 public void hqltest05(){155 Session session = null;156 try {157 session = HibernateUtil.openSession();158 session.beginTransaction();159 160 //查詢記錄的數量
161 Query q = session.createQuery("from Student s where s.classroom.id = ? and s.id in(:sids)");162 List<Student> ss = q.setParameter(0, 1).setParameterList("sids", new Object[]{1,3}).list();163 for (Student s : ss) {164 System.out.println(s.getName());165 }166 167 } catch (Exception e) {168 if (session != null) {169 session.getTransaction().rollback();170 }171 } finally{172 if (session != null) {173 session.close();174 }175 }176 }177 178 @SuppressWarnings("unchecked")179 @Test180 /**
181 * 內連接查詢
182 */183 public void hqltest06(){184 Session session = null;185 try {186 session = HibernateUtil.openSession();187 session.beginTransaction();188 189 //查詢記錄的數量
190 Query q = session.createQuery("select s from Student s join s.classroom cla where cla.id = 2");191 List<Student> ss = q.list();192 for (Student s : ss) {193 System.out.println(s.getName());194 }195 196 } catch (Exception e) {197 if (session != null) {198 session.getTransaction().rollback();199 }200 } finally{201 if (session != null) {202 session.close();203 }204 }205 }206 207 208 @SuppressWarnings("unchecked")209 @Test210 /**
211 * 實現一個類似報表的查詢
212 */213 public void hqltest07(){214 Session session = null;215 try {216 session = HibernateUtil.openSession();217 session.beginTransaction();218 219 //查詢記錄的數量
220 Query q = session.createQuery("select stu.name,stu.grade,cla.name,sp.name from Student stu " + "left join stu.classroom cla left join stu.classroom.specialty sp ");
221 List<Object[]> objs = q.list();222 for (Object[] s : objs) {223 System.out.println(s[0]+" -- "+ s[1]+" -- " + s[2] + " -- " +s[3] );224 }225 226 //基本的查詢會返回一個對象數組object[],但是如此一來,在控制層獲取會很困難
227 //所以,就需要創建一個dto對象來存儲這些查詢出的數據
228 //此處的dto對象ReportDto,其實體類中必須包含ReportDto(String name, String grade, String claName, String spName)形式的構造函數,才能如下書寫
229 Query q1 = session.createQuery("select new domain.ReportDto" + "(stu.name,stu.grade,cla.name,sp.name) from Student stu)"
+ "( left join stu.classroom cla left join stu.classroom.specialty sp ");
230 List<ReportDto> rds = q1.list();231 for (ReportDto rd : rds) {232 System.out.println(rd.getName()+" -- " +rd.getGrade()+" -- "+rd.getClaName()+" -- " + rd.getSpName());233 }234 235 } catch (Exception e) {236 e.printStackTrace();237 if (session != null) {238 session.getTransaction().rollback();239 }240 } finally{241 if (session != null) {242 session.close();243 }244 }245 }246 }247 說到HQL查詢,就要提到關聯對象間的延遲加載問題,hibernate中的抓取策略和延遲加載息息相關,基于XML配置類文件,通過XML的fetch配置可以自定義抓取策略,XML配置默認是select,也就是說,如果當前取得的對象中存在延遲加載對象,那么在取得延遲加載對象的時候,會通過select語句取得。如果配置為join,則會通過關聯方式取得。對于使用HQL查詢的對象無效,需要同過batch-size的設置,或者使用HQL的時候,在join關鍵后添加fetch關鍵字來抓取。基于注解的方式配置實體類,默認會通過關聯join的方式取得。不論是注解的方式還是XML的方式去配置實體類,配置中的抓取策略只針對load的對象有效,HQL查詢會忽略配置。