hibernate 數據庫查詢


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()來減少性能上的消耗;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM