【Hibernate】Hibernate的多表查詢,hibernate表查詢
在《【Hibernate】Hibernate的聚類查詢、分組查詢、排序與時間之差》(點擊開啟連結)一文中已經講述過如何利用HQL語句取代SQL語句,進行聚類查詢、分組查詢、排序與時間之差的查詢,同時指出hql能代替sql語句做任何事情。我原本以為hql語句的多表查詢,要先對裡面的實體做Java與xml的修改,其實並不需要,同樣是一句HQL語句就能搞定的事情。SQL的多表查詢已經在《【Mysql】利用內串連與巢狀查詢實現多表查詢,主鍵、外鍵的基本概念》(點擊開啟連結)講過。
比如如下的SQL語句:
select t1.Title,t1.Contentfrom blog as t1 ,usertable as t2where t1.userid=t2.id and t2.username='a'
轉換成HQL語句則如下:
String hql="select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'" List<Object> resultList = session.createQuery(hql).list(); for (int i = 0; i < resultList.size(); i++) { Object[] obj = (Object[])resultList.get(i); System.out.println(obj[0]+","+obj[1]); }
核心思想,是把sql語句中的表,寫成Hibernate的實體,sql語句中的欄位、列,寫成Hibernate的實體的成員變數,同時必須把表使用as進行t1,t2等標記,不能使用Blog.XX欄位來簡化,如上,就是Blog,Usertable兩張錶轉化為t1,t2標記,把sql的欄位、列,表對應轉化為Hibernate的實體成員變數,實體進行查詢。
Hibernate查詢出來的結果是一個存放Object數組的List,也就是說List的每項都是一個Object數組,Object數組的第n項對應查詢結果的第n項。
可以再進行下一步的處理。
下面用一個例子,來說明HQL語句的多表查詢。
,Blog記錄了使用者發表的部落格,usertable記錄了使用者的基本資料。Blog表中的userid與usertable的主鍵id形成參照完整性。
這兩張表在Hibernate的Java工程種分別對應如下實體:
Blog.java
import javax.persistence.*;@Entity@Table(name = "blog")public class Blog {private int id;private String title;private String content;private int userId;@Id@GeneratedValuepublic int getId() {return id;}public void setId(int id) {this.id = id;}@Column(name = "Title")public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}@Column(name = "Content")public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Column(name = "userid")public int getUserId() {return userId;}public void setUserId(int userId) {this.userId = userId;}@Overridepublic String toString() {return id + "," + title + "," + content + "," + userId;}}
Usertable.java
import javax.persistence.*;@Entity@Table(name = "usertable")public class Usertable {private int id;private String username;private String password;@Id@GeneratedValuepublic int getId() {return id;}public void setId(int id) {this.id = id;}@Column(name = "username")public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Column(name = "password")public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return id + "," + username + "," + password;}}
同時,hibernate.cfg.xml做如下的配置:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"><hibernate-configuration><session-factory><!--所用的資料庫驅動 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><!--所用的資料庫登陸密碼 --><property name="hibernate.connection.password">admin</property><!--所用的資料庫名稱為test,根據實際更改 --><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property><!--所用的資料庫使用者名稱 --><property name="hibernate.connection.username">pc</property><!--所用的資料庫方言,與所用資料庫驅動一樣,可以在網上查到,這裡是mysql --><property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property><property name="hibernate.format_sql">true</property><!--如果是update表明Hibernate將保留原來的資料記錄,插入時把新記錄添加到已有的表, --><!--如果是create,則總是建立新的表,如果原來資料庫已有的這個表,則這個表的記錄會被全部清洗 --><property name="hibernate.hbm2ddl.auto">update</property><!--羅列Testtable表與Java檔案的映射 --><!--將資料庫中的usertable表,blog表映射到Usertable.java與Blog.java兩個實體 --><mapping class="Usertable" /><mapping class="Blog" /></session-factory></hibernate-configuration>
可以發現,這沒有進行任何的參照完整性的指定。
下面,要查詢usertable中username為a的使用者,發表的Blog。
我們知道先要查詢username為a的使用者的id,之後利用這個查出來的id到Blog表中查詢。
用sql陳述式完成這個多表查詢,則這樣寫:
select t1.Title,t1.Contentfrom blog as t1 ,usertable as t2where t1.userid=t2.id and t2.username='a'
其查詢結果如下:
這使用Hibernate則這樣寫,在HibernateMultiTableTest.java中的代碼如下:
import java.util.List;import org.hibernate.*;import org.hibernate.cfg.*;class dbDAO {private Session session;// 建構函式,初始化Session,相當於串連資料庫public dbDAO() {// new Configuration().configure()是吧hibernate.cfg.xml中的所有配置讀取進來// .buildSessionFactory().openSession()是建立Session工廠並執行個體化sessionthis.session = new Configuration().configure().buildSessionFactory().openSession();}// 執行查詢public Query query(String hql) {return session.createQuery(hql);}// 執行插入、修改public void save(Object object) {Transaction transaction = session.beginTransaction();session.save(object);transaction.commit();}// 執行刪除public void delete(Object object) {Transaction transaction = session.beginTransaction();session.delete(object);transaction.commit();}// 解構函式,中斷Session,相當於中斷資料庫的串連protected void finalize() throws Exception {if (session.isConnected() || session != null) {session.close();}}}@SuppressWarnings("unchecked")public class HibernateMultiTableTest {public static void main(String args[]) {dbDAO db = new dbDAO();List<Object> resultList = db.query("select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'").list();//HQL的多表查詢System.out.println("usertable中username為a的使用者,發表的內容如下:");System.out.println();for (int i = 0; i < resultList.size(); i++) {Object[] obj = (Object[]) resultList.get(i);System.out.println("標題:" + obj[0]);System.out.println("內容:" + obj[1]);System.out.println();}}}
其運行結果如下: