在Hibernate中的HQL语句其实能够基本能够实现SQL语句所做的事情,正如jQuery至于javascript一样。虽然HQL语句是对类的查询,但是HQL在实行聚类查询、分组查询、排序与时间之差等查询,也无须把查询结果查询出来,再通过对List的处理才得到结果。
比如有一张如下的Testtable表:
要像《【Mysql】求出离最近相差X天的项,sql语句关于日期的比对》(点击打开链接)一样,查询date字段离现在具有30年的项有多少,SQL语句则这样写:
select count(*) from testtable where timestampdiff(year,date,now())<30;其查询结果如下图:
在Hibernate中的Java语句则如下实现,同时这样输出:
String hql="select count(*) from Testtable t where timestampdiff(year,t.date,now())<30" String result=session.createQuery(hql).uniqueResult().toString(); System.out.println(result);这里利用了纯粹的HQL查询,同时返回结果唯一。省略Hibernate的初始化与配置等。
直接利用uniqueResult()的方法即可。
如果,查询结果是多行的情况,比如还是对刚才的Testtable表进行查询,
这次查询的是在《【Mysql】利用group by附带having进行聚类查询》(点击打开链接)查询过的,在username出现次数多于1次,不含1次的项,并且降序排列,那么sql语句则这样写:
select username,count(*) from testtable group by username having coutn(*)>1 order by count(*) desc其查询结果如下图:
在Hibernate中的Java程序则如下写,关键是把查询结果的每一行转化成Object数组,则对Object数组的每一项进行强制类型的转化,则可以完成处理:
String hql="SELECT t.username,count(*) FROM Testtable t group by t.username having count(*)>1 order by count(*) desc" 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]); }这里利用了纯粹的HQL查询,也省略Hibernate的初始化与配置等。如果你要利用到查询结果做后续工作,
则可以,这样处理:
String username=(String)obj[0];
关键是,在要查询的类中,后面补一个替换名称,比如Testtable就替换为t,就可以顺利操作了。
上述省略整个HQL初始化与布置的过程,具体请看《【Hibernate】Hibernate的层次划分,Hibernate4.3的初始化的新写法》(点击打开链接),不再赘述。
其中,这里的目录结构是这样的:
其中,
dbDAO.java,数据库业务类,一字未改,多次复用:
import org.hibernate.*; import org.hibernate.cfg.*; import org.hibernate.service.*; import org.hibernate.boot.registry.*; public class dbDAO { private Session session; // 构造函数,初始化Session,相当于连接数据库 public dbDAO() { //这里使用了Hibernate4.3.8的写法,这里Hibernate又把初始化的方法修改了,非常蛋疼 Configuration cfg = new Configuration().configure(); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() .applySettings(cfg.getProperties()).build(); SessionFactory sessionFactory = cfg .buildSessionFactory(serviceRegistry); this.session = sessionFactory.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(); } } }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文件的映射,这里就Testtable.java的一张表,所以就写一个Testtable.java --> <mapping class="Testtable" /> </session-factory> </hibernate-configuration>Testtable.java,数据库持久化类的内容如下,只是把数据库中的testtable表的所有东西映射过来:
import javax.persistence.*; @Entity @Table(name = "testtable") public class Testtable { private int id; private String username; private String number; private String date; // 表示主键与自动生成项 @Id @GeneratedValue public 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 = "number") public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } @Column(name = "date") public String getDate() { return date; } public void setDate(String date) { this.date = date; } @Override public String toString() { return id + "," + username + "," + number + "," + date; } }最关键的是控制层方法实现类,HQL.java,就是把上面所介绍的Hibernate的聚类查询、分组查询、排序与时间之差查询利用dbDAO.java的封装,一一实现:
import java.util.*; @SuppressWarnings("unchecked") public class HQL { public static void main(String[] args) { // 建立DAO类 dbDAO db = new dbDAO(); // 如果返回值是唯一的,则用uniqueResult()方法 String result = db .query("select count(*) from Testtable t where timestampdiff(year,t.date,now())<30") .uniqueResult().toString(); System.out.println(result); System.out.println(); // 排序与聚类查询(分组查询) List<Object> resultList = db .query("SELECT t.username,count(*) FROM Testtable t group by t.username having count(*)>1 order by count(*) desc") .list(); for (int i = 0; i < resultList.size(); i++) { Object[] obj = (Object[]) resultList.get(i); System.out.println(obj[0] + "," + obj[1]); } } }运行结果如下图:
【Hibernate】Hibernate的聚类查询、分组查询、排序与时间之差
原文:http://blog.csdn.net/yongh701/article/details/45147213