【Hibernate】Hibernate的多表查询

来源:互联网 发布:感觉自己很冷漠知乎 编辑:程序博客网 时间:2024/05/21 08:43

在《【hibernate】Hibernate的聚类查询、分组查询、排序与时间之差》(点击打开链接)一文中已经讲述过如何利用HQL语句取代SQL语句,进行聚类查询、分组查询、排序与时间之差的查询,同时指出hql能代替sql语句做任何事情。我原本以为hql语句的多表查询,要先对里面的实体做Java与xml的修改,其实并不需要,同样是一句HQL语句就能搞定的事情。SQL的多表查询已经在《【MySQL】利用内连接与嵌套查询实现多表查询,主键、外键的基本概念》(点击打开链接)讲过。

比如如下的SQL语句:

[sql] view plain copy print?
  1. select t1.Title,t1.Content  
  2. from blog as t1 ,usertable as t2  
  3. where t1.userid=t2.id and t2.username='a'  

转换成HQL语句则如下:
[java] view plain copy print?
  1. String hql="select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'"    
  2. List<Object> resultList = session.createQuery(hql).list();    
  3. for (int i = 0; i < resultList.size(); i++) {    
  4.     Object[] obj = (Object[])resultList.get(i);    
  5.     System.out.println(obj[0]+","+obj[1]);    
  6. }  

核心思想,是把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

[java] view plain copy print?
  1. import javax.persistence.*;  
  2.   
  3. @Entity  
  4. @Table(name = "blog")  
  5. public class Blog {  
  6.     private int id;  
  7.     private String title;  
  8.     private String content;  
  9.     private int userId;  
  10.   
  11.     @Id  
  12.     @GeneratedValue  
  13.     public int getId() {  
  14.         return id;  
  15.     }  
  16.   
  17.     public void setId(int id) {  
  18.         this.id = id;  
  19.     }  
  20.   
  21.     @Column(name = "Title")  
  22.     public String getTitle() {  
  23.         return title;  
  24.     }  
  25.   
  26.     public void setTitle(String title) {  
  27.         this.title = title;  
  28.     }  
  29.   
  30.     @Column(name = "Content")  
  31.     public String getContent() {  
  32.         return content;  
  33.     }  
  34.   
  35.     public void setContent(String content) {  
  36.         this.content = content;  
  37.     }  
  38.   
  39.     @Column(name = "userid")  
  40.     public int getUserId() {  
  41.         return userId;  
  42.     }  
  43.   
  44.     public void setUserId(int userId) {  
  45.         this.userId = userId;  
  46.     }  
  47.   
  48.     @Override  
  49.     public String toString() {  
  50.         return id + "," + title + "," + content + "," + userId;  
  51.     }  
  52.   
  53. }  
Usertable.java
[java] view plain copy print?
  1. import javax.persistence.*;  
  2.   
  3. @Entity  
  4. @Table(name = "usertable")  
  5. public class Usertable {  
  6.     private int id;  
  7.     private String username;  
  8.     private String password;  
  9.   
  10.     @Id  
  11.     @GeneratedValue  
  12.     public int getId() {  
  13.         return id;  
  14.     }  
  15.   
  16.     public void setId(int id) {  
  17.         this.id = id;  
  18.     }  
  19.   
  20.     @Column(name = "username")  
  21.     public String getUsername() {  
  22.         return username;  
  23.     }  
  24.   
  25.     public void setUsername(String username) {  
  26.         this.username = username;  
  27.     }  
  28.   
  29.     @Column(name = "password")  
  30.     public String getPassword() {  
  31.         return password;  
  32.     }  
  33.   
  34.     public void setPassword(String password) {  
  35.         this.password = password;  
  36.     }  
  37.   
  38.     @Override  
  39.     public String toString() {  
  40.         return id + "," + username + "," + password;  
  41.     }  
  42. }  

同时,hibernate.cfg.xml做如下的配置:

[html] view plain copy print?
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <!DOCTYPE hibernate-configuration PUBLIC    
  3.     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"    
  4.     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">  
  5. <hibernate-configuration>  
  6.     <session-factory>  
  7.         <!--所用的数据库驱动 -->  
  8.         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
  9.         <!--所用的数据库登陆密码 -->  
  10.         <property name="hibernate.connection.password">admin</property>  
  11.         <!--所用的数据库名称为test,根据实际更改 -->  
  12.         <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property>  
  13.         <!--所用的数据库用户名 -->  
  14.         <property name="hibernate.connection.username">pc</property>  
  15.         <!--所用的数据库方言,与所用数据库驱动一样,可以在网上查到,这里是mysql -->  
  16.         <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>  
  17.         <property name="hibernate.format_sql">true</property>  
  18.         <!--如果是update表明Hibernate将保留原来的数据记录,插入时把新记录添加到已有的表, -->  
  19.         <!--如果是create,则总是创建新的表,如果原来数据库已有的这个表,则这个表的记录会被全部清洗 -->  
  20.         <property name="hibernate.hbm2ddl.auto">update</property>  
  21.         <!--罗列Testtable表与Java文件的映射 -->  
  22.         <!--将数据库中的usertable表,blog表映射到Usertable.java与Blog.java两个实体 -->  
  23.         <mapping class="Usertable" />  
  24.         <mapping class="Blog" />  
  25.     </session-factory>  
  26. </hibernate-configuration>    
可以发现,这没有进行任何的参照完整性的指定。下面,要查询usertable中username为a的用户,发表的Blog。

我们知道先要查询username为a的用户的id,之后利用这个查出来的id到Blog表中查询。

用sql语句完成这个多表查询,则这样写:

[sql] view plain copy print?
  1. select t1.Title,t1.Content  
  2. from blog as t1 ,usertable as t2  
  3. where t1.userid=t2.id and t2.username='a'  
其查询结果如下:


这使用Hibernate则这样写,在HibernateMultiTableTest.java中的代码如下:

[java] view plain copy print?
  1. import java.util.List;  
  2.   
  3. import org.hibernate.*;  
  4. import org.hibernate.cfg.*;  
  5.   
  6. class dbDAO {  
  7.     private Session session;  
  8.   
  9.     // 构造函数,初始化Session,相当于连接数据库  
  10.     public dbDAO() {  
  11.         // new Configuration().configure()是吧hibernate.cfg.xml中的所有配置读取进来  
  12.         // .buildSessionFactory().openSession()是创建Session工厂并实例化session  
  13.         this.session = new Configuration().configure().buildSessionFactory()  
  14.                 .openSession();  
  15.     }  
  16.   
  17.     // 执行查询  
  18.     public Query query(String hql) {  
  19.         return session.createQuery(hql);  
  20.     }  
  21.   
  22.     // 执行插入、修改  
  23.     public void save(Object object) {  
  24.         Transaction transaction = session.beginTransaction();  
  25.         session.save(object);  
  26.         transaction.commit();  
  27.     }  
  28.   
  29.     // 执行删除  
  30.     public void delete(Object object) {  
  31.         Transaction transaction = session.beginTransaction();  
  32.         session.delete(object);  
  33.         transaction.commit();  
  34.     }  
  35.   
  36.     // 析构函数,中断Session,相当于中断数据库的连接  
  37.     protected void finalize() throws Exception {  
  38.         if (session.isConnected() || session != null) {  
  39.             session.close();  
  40.         }  
  41.     }  
  42.   
  43. }  
  44.   
  45. @SuppressWarnings("unchecked")  
  46. public class HibernateMultiTableTest {  
  47.     public static void main(String args[]) {  
  48.         dbDAO db = new dbDAO();  
  49.         List<Object> resultList = db  
  50.                 .query("select t1.title,t1.content from Blog as t1,Usertable as t2 where t1.userId=t2.id and t2.username='a'")  
  51.                 .list();//HQL的多表查询  
  52.         System.out.println("usertable中username为a的用户,发表的内容如下:");  
  53.         System.out.println();  
  54.         for (int i = 0; i < resultList.size(); i++) {  
  55.             Object[] obj = (Object[]) resultList.get(i);  
  56.             System.out.println("标题:" + obj[0]);  
  57.             System.out.println("内容:" + obj[1]);  
  58.             System.out.println();  
  59.         }  
  60.     }  
  61. }  
其运行结果如下:

转载自:yongh701

0 0