hibernate提供了多種方式進行數據庫數據的查詢
HQL查詢
代碼如下
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 Query query = session.createQuery("from Student student where student.name like :name order by student.id asc"); 7 query.setParameter("name", "student%"); 8 //實現分頁 9 query.setFirstResult(0); 10 query.setMaxResults(2); 11 List<Student> students = query.list(); 12 for(Student student : students) { 13 System.out.println(student.getName()); 14 } 15 16 tx.commit(); 17 HibernateFactory.closeSession(); 18 } 19 }
如果結果是單一的對象而不是集合,可以使用query. uniqueResult()
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 Query query = session.createQuery("select count(*) from Student"); 7 Long count = (Long)query.uniqueResult(); 8 9 tx.commit(); 10 HibernateFactory.closeSession(); 11 } 12 }
也可以直接訪問對象中的對象屬性(String hql = "from Student where grade.name= 'grade1'";) 這樣相當於兩張表的聯合查詢
如果一次查詢多個對象,可以使用以下方式
1 public class HibernateTest { 2 public static void main(String[] args) { 3 4 Session session = HibernateFactory.currentSession(); 5 Transaction tx = session.beginTransaction(); 6 7 Query query = session.createQuery("from Student s,Grade g where s.id=g.id and s.name like :name"); 8 query.setParameter("name", "student%"); 9 List list = query.list(); 10 for(int i = 0;i < list.size();i++) { 11 Object[] obj = (Object[]) list.get(i); 12 Student student = (Student) obj[0]; 13 Grade grade = (Grade)obj[1]; 14 System.out.println(student.getName() + "|" + grade.getName()); 15 } 16 17 tx.commit(); 18 HibernateFactory.closeSession(); 19 } 20 }
Criteria方式查詢
代碼如下
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 Criteria criteria = session.createCriteria(Student.class); 7 criteria.add(Restrictions.like("name", "student%")); 8 9 criteria.setFirstResult(0); 10 criteria.setMaxResults(2); 11 criteria.addOrder(Order.desc("name")); 12 13 List<Student> students = criteria.list(); 14 for(Student student : students) { 15 System.out.println(student.getName()); 16 } 17 18 tx.commit(); 19 HibernateFactory.closeSession(); 20 } 21 }
使用criteria方式查詢有以下三個步驟
1.使用Session實例 的createCriteria()方法創建Criteria對象
2.使用工具類Restrictions的方法為Criteria對象設置查詢條件,Order工具類的方法設置排序方式,Projections工具類的方法進行統計和分組
3.使用Criteria對象的list()方法進行查詢並返回結果
例子查詢
例子查詢將一個對象的非空屬性作為查詢條件進行查詢,代碼如下
1 public class HibernateTest { 2 public static void main(String[] args) { 3 //建立一個例子對象,它的非空屬性作為刪選條件 4 Student studentExample = new Student(); 5 studentExample.setName("student1"); 6 7 Session session = HibernateFactory.currentSession(); 8 Transaction tx = session.beginTransaction(); 9 10 Criteria criteria = session.createCriteria(Student.class); 11 criteria.add(Example.create(studentExample)); 12 13 List<Student> students = criteria.list(); 14 for(Student student : students) { 15 System.out.println(student.getName()); 16 } 17 18 tx.commit(); 19 HibernateFactory.closeSession(); 20 } 21 }
離線查詢
離線查詢建立一個DetachedCriteria對象,將查詢的條件等指定好,然后在session.beginTransaction()后將這個對象傳入,代碼如下
1 public class HibernateTest { 2 public static void main(String[] args) { 3 DetachedCriteria dc = DetachedCriteria.forClass(Student.class); 4 dc.add(Restrictions.like("name", "student%")); 5 6 Session session = HibernateFactory.currentSession(); 7 Transaction tx = session.beginTransaction(); 8 9 Criteria criteria = dc.getExecutableCriteria(session); 10 List<Student> students = criteria.list(); 11 for(Student student : students) { 12 System.out.println(student.getName()); 13 } 14 15 tx.commit(); 16 HibernateFactory.closeSession(); 17 } 18 }
load/get方式
Student student = (Student) session.get(Student.class, 1);
Student student = (Student) session.load(Student.class, 1);
兩者區別
1.get()采用立即加載方式,而load()采用延遲加載;get()方法執行的時候,會立即向數據庫發出查詢語句, 而load()方法返回的是一個代理(此代理中只有一個id屬性),只有等真正使用該對象屬性的時候,才會發出sql語句
2.如果數據庫中沒有對應的記錄,get()方法返回的是null.而load()方法出現異常ObjectNotFoundException
命名查詢
1.配置hbm文件,將sql或者hql語句寫入hbm,並給與一個唯一標示這個查詢語句的name
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping > 6 <class>...</class> 7 8 <query name="hqlquery"> 9 <![CDATA[ 10 from Student where name like :name 11 ]]> 12 </query> 13 14 <query name="sqlquery"> 15 <![CDATA[ 16 select s from Student s where name like ? 17 ]]> 18 </query> 19 </hibernate-mapping>
2.通過name在代碼中調用事先寫好的查詢語句
1 public class HibernateTest { 2 public static void main(String[] args) { 3 4 Session session = HibernateFactory.currentSession(); 5 Transaction tx = session.beginTransaction(); 6 7 Query query = session.getNamedQuery("hqlquery"); 8 query.setParameter("name", "student%"); 9 List<Student> students = query.list(); 10 for(Student student : students) { 11 System.out.println(student.getName()); 12 } 13 14 Query sqlquery = session.getNamedQuery("sqlquery"); 15 sqlquery.setParameter(0, "student%"); 16 List<Student> students2 = query.list(); 17 for(Student student : students2) { 18 System.out.println(student.getName()); 19 } 20 21 22 tx.commit(); 23 HibernateFactory.closeSession(); 24 } 25 }
SQL查詢
hibernate支持原生的sql查詢語句,具體的代碼如下
返回單表的查詢
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 List<Student> students = session.createSQLQuery("select * from student").addEntity(Student.class).list(); 7 //或者采用以下語句 8 // List<Student> students = session.createSQLQuery("select s.* from student as s").addEntity("s",Student.class).list(); 9 10 for(Student student : students) { 11 System.out.println(student.getName()); 12 } 13 14 tx.commit(); 15 HibernateFactory.closeSession(); 16 } 17 }
返回多個表的查詢
1 public class HibernateTest { 2 public static void main(String[] args) { 3 Session session = HibernateFactory.currentSession(); 4 Transaction tx = session.beginTransaction(); 5 6 SQLQuery query = session.createSQLQuery("select s.*,g.* from student as s,grade as g where s.gradeid=g.id"); 7 query.addEntity("s",Student.class).addEntity("g",Grade.class); 8 9 List list = query.list(); 10 //list的每一條數據都由Object數組組成,數組的每個約束對應一個對象 11 for (int i = 0; i < list.size(); i++) { 12 Object[] obj = (Object[]) list.get(i); 13 Student student = (Student) obj[0]; 14 Grade grade = (Grade) obj[1]; 15 } 16 17 tx.commit(); 18 HibernateFactory.closeSession(); 19 } 20 }
使用jdbc
1 public class HibernateTest { 2 public static void main(String[] args) { 3 4 Session session = HibernateFactory.currentSession(); 5 Transaction tx = session.beginTransaction(); 6 session.doWork(new Work() { 7 public void execute(Connection connection) throws SQLException { 8 // 這里已經得到connection了,可以繼續你的JDBC代碼。 9 PreparedStatement ps = connection.prepareStatement("insert into student(id,name) values(?,?)"); 10 for(int i = 0;i < 500;i++) { 11 ps.setInt(1,i); 12 ps.setString(2,"student" + i); 13 ps.addBatch(); //添加到批處理命令中 14 } 15 ps.executeBatch(); //執行批處理命令 16 // 注意不要close了這個connection。 17 } 18 }); 19 20 //事務提交后才會執行插入操作 21 tx.commit(); 22 HibernateFactory.closeSession(); 23 } 24 }
使用原生的jdbc操作,hibernate4之前可以用session.connection()獲取Connection對象,Hibernate4之后這個方法已經廢棄
Query.iterator與Query.list的比較
iterator的使用方法如下
1 public class HibernateTest { 2 public static void main(String[] args) { 3 4 Session session = HibernateFactory.currentSession(); 5 Transaction tx = session.beginTransaction(); 6 7 Query query = session.createQuery("from Student"); 8 Iterator iterator = query.iterate(); 9 while(iterator.hasNext()) { 10 Student student = (Student)iterator.next(); 11 System.out.println(student.getName()); 12 } 13 14 tx.commit(); 15 HibernateFactory.closeSession(); 16 } 17 }
iterator方式查詢產生的sql語句如下
1 Hibernate: select student0_.id as col_0_0_ from student student0_ 2 3 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 4 5 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 6 7 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 8 9 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 10 11 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 12 13 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 14 15 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=? 16 17 Hibernate: select student0_.id as id1_1_0_, student0_.name as name2_1_0_, student0_.gradeid as gradeid3_1_0_ from student student0_ where student0_.id=?
通過list方式查詢產生的sql語句如下
1 Hibernate: select student0_.id as id1_1_, student0_.name as name2_1_, student0_.gradeid as gradeid3_1_ from student student0_
兩者相比較,list()只發一條語句將符合條件的數據全部查出,而iterator()卻現將id查出來,然后根據id再將符合條件的數據查出,這就構成了N+1的問題;既然list更高效,為什么hibernate還將iterator存在呢?
執行以下程序
1 public class HibernateTest { 2 public static void main(String[] args) { 3 4 Session session = HibernateFactory.currentSession(); 5 Transaction tx = session.beginTransaction(); 6 String hql = "from Student"; 7 8 Query listQuery = session.createQuery(hql); 9 List<Student> list = listQuery.list(); 10 for(Student student : list) { 11 System.out.println(student.getName()); 12 } 13 14 Query iteratorQuery = session.createQuery(hql); 15 Iterator iterator = iteratorQuery.iterate(); 16 while(iterator.hasNext()) { 17 Student student = (Student)iterator.next(); 18 System.out.println(student.getName()); 19 } 20 21 tx.commit(); 22 HibernateFactory.closeSession(); 23 } 24 }
最終產生的sql語句如下
1 Hibernate: select student0_.id as id1_1_, student0_.name as name2_1_, student0_.gradeid as gradeid3_1_ from student student0_ 2 Hibernate: select student0_.id as col_0_0_ from student student0_
將list()和iterator()放在一起使用,這時的iterator只執行了一條SQL,原因在於hibernate的緩存機制
list()方法將執行Select SQL從數據庫中獲取所有符合滿足條件的記錄並構造相應的實體對象,實體對象構建完畢后,就將其納入緩存;
這樣等到iterator()執行時,首先會執行一條SQL來查詢符合條件數據的id,隨即,iterator方法首先在本地緩存內根據id查找對應的實體對象是否存在,如果緩存中已經存在對應的數據,則直接以此數據對象作為查詢結果;如果沒有找到,則再次執行Select語句獲得對應數據庫中的表記錄(如果iterator在數據庫中查到並構建了完整的數據對象,也會將其納入緩存中);
list()方法無法讀取緩存,但它可以寫入緩存,在上面這個實例中,list()將讀取的數據放入緩存中,iterator()直接可以用於是出現了以上的結果;
如果目標數據只讀或者讀取相當頻繁,可以使用iterator()來減少性能上的消耗;