首页 > Java开发 > HQL使用小技巧——混合SQL

HQL使用小技巧——混合SQL

偶然间发现HQL一个非常有意思的用法,拿来分享下。

示例如下:

1. student数据库表(MySQL)

[sql][/sql] view plaincopy

  1. CREATE TABLE `student` (
  2.   `ID` int(11) NOT NULL,
  3.   `NAMES` varchar(50) NOT NULL,
  4.   `AGE` int(3) NOT NULL,
  5.   PRIMARY KEY (`ID`)
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表中数据

ID NAMES AGE
1 王鹏 24
2 张三 12

2. student实体类

[java][/java] view plaincopy

  1. @Entity
  2. @Table(name = "STUDENT")
  3. public class Student {
  4.     private int id;
  5.     private String names;
  6.     private int age;
  7.     @Id
  8.     @GeneratedValue(strategy = GenerationType.IDENTITY)
  9.     @Column(name = "ID", unique = true, nullable = false)
  10.     public int getId() {
  11.         return id;
  12.     }
  13.     public void setId(int id) {
  14.         this.id = id;
  15.     }
  16.     @Column(name = "NAMES", length = 50, nullable = false)
  17.     public String getNames() {
  18.         return names;
  19.     }
  20.     public void setNames(String names) {
  21.         this.names = names;
  22.     }
  23.     @Column(name = "AGE", length = 3, nullable = false)
  24.     public int getAge() {
  25.         return age;
  26.     }
  27.     public void setAge(int age) {
  28.         this.age = age;
  29.     }
  30. }

3. HQL语句

[java][/java] view plaincopy

  1.     public void hql() {
  2.         int age = 10;
  3.         Session session = sessionFactory.getCurrentSession();
  4.         String hql = "from Student where age > ?";
  5.         Query query = session.createQuery(hql);
  6.         query.setInteger(0, age);
  7. //      query.setParameter(0, age);
  8.         List<Student> students = query.list();
  9.         System.out.println(students.size());
  10.     }

当HQL有参数且知道参数类型,我们可以采用类似query.setInteger(0, age)语句来设置,如果不知道参数类型,我们采用query.setParameter(0, age)语句。但是当使用query.setParameter(0, age)时,如果age类型与Student实体类中age类型不一致时,就会报类型转换异常,如:

[java][/java] view plaincopy

  1. public void hql() {
  2.     String age = "10";
  3.     Session session = sessionFactory.getCurrentSession();
  4.     String hql = "from Student where age > ?";
  5.     Query query = session.createQuery(hql);
  6. /       query.setInteger(0, age);
  7.     query.setParameter(0, age);
  8.     List<Student> students = query.list();
  9.     System.out.println(students.size());
  10. }

将报异常java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer。

但是我们知道当我们用原生SQL时,SQL语句其实是不关心参数类型的,例如:

[java][/java] view plaincopy

  1. String sql = "select * from student where AGE > " + age;

HQL之所以会关心变量类型,是因为HQL语句是基于对象的查询语句,最终需要将对象查询语句变为SQL语句,那么在解析时必然会考虑变量类型。那有什么解决办法呢?

其实HQL是支持SQL语句的,注意:我说支持不是说把HQL写成sql,而是支持混合写法,如下所示:

[java][/java] view plaincopy

  1. public void hql() {
  2.     String age = "10";
  3.     Session session = sessionFactory.getCurrentSession();
  4.     String hql = "from Student where AGE > ?";
  5.     Query query = session.createQuery(hql);
  6.     query.setParameter(0, age);
  7.     List<Student> students = query.list();
  8.     System.out.println(students.size());
  9. }

注意String hql = "from Student where AGE > ?"中HQL语句的写法。

from Student是基于HQL的,而AGE却是SQL写法,这样写后就不会再报类型转换错误的异常了,这是因为Hibernagte在解析HQL语句时,最终会将HQL变为SQL,因此如果语句中含有SQL语句部分的话,就不会再解析转换了,

诸如如上情况的,再看个例子:

[java][/java] view plaincopy

  1. public void hql() {
  2.     int id = 1;
  3.     String age = "10";
  4.     Session session = sessionFactory.getCurrentSession();
  5.     String hql = "from Student where AGE > ? and id = ?";
  6.     Query query = session.createQuery(hql);
  7.     query.setParameter(0, age);
  8.     query.setInteger(1, id);
  9.     List<Student> students = query.list();
  10.     System.out.println(students.size());
  11. }

可以看到HQL中夹杂着SQL语句。

 

这算是一个小发现吧,希望会帮助到一些朋友。


本文固定链接: http://www.devba.com/index.php/archives/2011.html | 开发吧

报歉!评论已关闭.