通过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查询会忽略配置。