欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

在Java的Hibernate框架中对数据库数据进行查询操作

程序员文章站 2024-03-08 17:25:53
hibernate查询语言(hql)是一种面向对象的查询语言,类似于sql,但不是对表和列操作,hql适用于持久对象和它们的属性。 hql查询由hibernate转换成传统...

hibernate查询语言(hql)是一种面向对象的查询语言,类似于sql,但不是对表和列操作,hql适用于持久对象和它们的属性。 hql查询由hibernate转换成传统的sql查询,这在圈上的数据库执行操作。

虽然可以直接使用sql语句和hibernate使用原生sql,但建议使用hql尽可能避免数据库可移植性的麻烦,并采取hibernate的sql生成和缓存策略的优势。

都像select,from和where等关键字不区分大小写,但如表名和列名的属性是区分在hql敏感。

from 语句
使用from子句,如果要加载一个完整的持久化对象到内存中。下面是一个使用from子句的简单的语法:

string hql = "from employee";
query query = session.createquery(hql);
list results = query.list();

如果需要完全限定在hql一个类名,只需指定如下的包和类名:
string hql = "from com.hibernatebook.criteria.employee";
query query = session.createquery(hql);
list results = query.list();

as 语句
as子句可以用来别名分配给类中的hql查询,特别是当有很长的查询。例如,我们前面简单的例子是以下几点:

string hql = "from employee as e";
query query = session.createquery(hql);
list results = query.list();

as关键字是可选的,也可以直接在之后的类名指定别名,如下所示:

string hql = "from employee e";
query query = session.createquery(hql);
list results = query.list();

select 子句
select子句提供了更多的控制权比from子句的结果集。如果想获得对象而不是整个对象的几个属性,使用select子句。下面是一个使用select语句来获取employee对象只是first_name字段的简单的语法:

string hql = "select e.firstname from employee e";
query query = session.createquery(hql);
list results = query.list();

值得注意的是在这里,employee.firstname是employee对象的一个属性,而不是employee表的一个字段。

where 子句
如果想缩小了从存储返回的特定对象,可以使用where子句。下面是一个使用where子句的简单的语法:

string hql = "from employee e where e.id = 10";
query query = session.createquery(hql);
list results = query.list();

order by 子句
若要排序hql查询的结果,将需要使用order by子句。您可以在结果集按升序(asc)或降序(desc)通过在对象的任何属性排序结果。下面是一个使用order by子句的简单的语法:

string hql = "from employee e where e.id > 10 order by e.salary desc";
query query = session.createquery(hql);
list results = query.list();

如果想通过一个以上的属性进行排序,你会仅仅是额外的属性添加到由子句用逗号隔开,如下所示的命令的结尾:

string hql = "from employee e where e.id > 10 " +
       "order by e.firstname desc, e.salary desc ";
query query = session.createquery(hql);
list results = query.list();

group by 子句
该子句允许从hibernate的它基于属性的值的数据库和组提取信息,并且通常使用结果包括总值。下面是一个使用group by子句的语法很简单:

string hql = "select sum(e.salary), e.firtname from employee e " +
       "group by e.firstname";
query query = session.createquery(hql);
list results = query.list();

使用命名参数
hibernate命名在其hql查询参数支持。这使得编写接受来自用户的输入容易,不必对sql注入攻击防御hql查询。下面是一个使用命名参数的简单的语法:

string hql = "from employee e where e.id = :employee_id";
query query = session.createquery(hql);
query.setparameter("employee_id",10);
list results = query.list();

update 子句
批量更新是新的hql与hibernate3,以及不同的删除工作,在hibernate 3和hibernate2一样。 query接口现在包含一个名为executeupdate()方法用于执行hql update或delete语句。

在update子句可以用于更新一个或多个对象中的一个或多个属性。下面是一个使用update子句的简单的语法:

string hql = "update employee set salary = :salary " + 
       "where id = :employee_id";
query query = session.createquery(hql);
query.setparameter("salary", 1000);
query.setparameter("employee_id", 10);
int result = query.executeupdate();
system.out.println("rows affected: " + result);

delete 子句
delete子句可以用来删除一个或多个对象。下面是一个使用delete子句的简单的语法:

string hql = "delete from employee " + 
       "where id = :employee_id";
query query = session.createquery(hql);
query.setparameter("employee_id", 10);
int result = query.executeupdate();
system.out.println("rows affected: " + result);

insert 子句
hql支持insert into子句中只记录在那里可以插入从一个对象到另一个对象。以下是使用insert into子句的简单的语法:

string hql = "insert into employee(firstname, lastname, salary)" + 
       "select firstname, lastname, salary from old_employee";
query query = session.createquery(hql);
int result = query.executeupdate();
system.out.println("rows affected: " + result);

聚合方法
hql支持多种聚合方法,类似于sql。他们工作在hql同样的方式在sql和下面的可用功能列表:

在Java的Hibernate框架中对数据库数据进行查询操作

distinct关键字只计算在该行设定的唯一值。下面的查询将只返回唯一的计数:

string hql = "select count(distinct e.firstname) from employee e";
query query = session.createquery(hql);
list results = query.list();

使用查询分页
有用于分页查询接口的两个方法。

  • query setfirstresult(int startposition)
  • query setmaxresults(int maxresult)

采用上述两种方法一起,可以在网站或swing应用程序构建一个分页组件。下面是例子,可以扩展来获取10行:

string hql = "from employee";
query query = session.createquery(hql);
query.setfirstresult(1);
query.setmaxresults(10);
list results = query.list();

查询条件
hibernate提供了操作对象,并依次数据在rdbms表可用的备用方式。其中一个方法是标准的api,它允许你建立一个标准的查询对象编程,可以套用过滤规则和逻辑条件。
hibernate的session接口提供了可用于创建一个返回的持久化对象的类的实例时,应用程序执行一个条件查询一个criteria对象createcriteria()方法。

以下是最简单的一个条件查询的例子是将简单地返回对应于employee类的每个对象。

criteria cr = session.createcriteria(employee.class);
list results = cr.list();

限制与标准:
可以使用add()方法可用于criteria对象添加限制条件查询。下面是例子增加一个限制与薪水返回的记录是等于2000:

criteria cr = session.createcriteria(employee.class);
cr.add(restrictions.eq("salary", 2000));
list results = cr.list();

以下是几个例子覆盖不同的场景,并且可以根据要求使用:

criteria cr = session.createcriteria(employee.class);

// to get records having salary more than 2000
cr.add(restrictions.gt("salary", 2000));

// to get records having salary less than 2000
cr.add(restrictions.lt("salary", 2000));

// to get records having fistname starting with zara
cr.add(restrictions.like("firstname", "zara%"));

// case sensitive form of the above restriction.
cr.add(restrictions.ilike("firstname", "zara%"));

// to get records having salary in between 1000 and 2000
cr.add(restrictions.between("salary", 1000, 2000));

// to check if the given property is null
cr.add(restrictions.isnull("salary"));

// to check if the given property is not null
cr.add(restrictions.isnotnull("salary"));

// to check if the given property is empty
cr.add(restrictions.isempty("salary"));

// to check if the given property is not empty
cr.add(restrictions.isnotempty("salary"));
可以创建and或or使用logicalexpression限制如下条件:

criteria cr = session.createcriteria(employee.class);

criterion salary = restrictions.gt("salary", 2000);
criterion name = restrictions.ilike("firstnname","zara%");

// to get records matching with or condistions
logicalexpression orexp = restrictions.or(salary, name);
cr.add( orexp );


// to get records matching with and condistions
logicalexpression andexp = restrictions.and(salary, name);
cr.add( andexp );

list results = cr.list();

虽然上述所有条件,可以直接使用hql在前面的教程中介绍。

分页使用标准:
还有的标准接口,用于分页的两种方法。

  • public criteria setfirstresult(int firstresult)
  • public criteria setmaxresults(int maxresults)

采用上述两种方法一起,我们可以在我们的网站或swing应用程序构建一个分页组件。下面是例子,可以扩展来每次获取10行:

criteria cr = session.createcriteria(employee.class);
cr.setfirstresult(1);
cr.setmaxresults(10);
list results = cr.list();

排序的结果:
标准的api提供了org.hibernate.criterion.order类排序按升序或降序排列你的结果集,根据对象的属性。这个例子演示了如何使用order类的结果集进行排序:

criteria cr = session.createcriteria(employee.class);
// to get records having salary more than 2000
cr.add(restrictions.gt("salary", 2000));

// to sort records in descening order
crit.addorder(order.desc("salary"));

// to sort records in ascending order
crit.addorder(order.asc("salary"));

list results = cr.list();

预测与聚合:
该criteria api提供了一个org.hibernate.criterion.projections类可用于获取平均值,最大值或最小值的属性值。projections类是类似于类限制,因为它提供了几个静态工厂方法用于获得projection 实例。  provides the

以下是涉及不同的方案的一些例子,可按规定使用:

criteria cr = session.createcriteria(employee.class);

// to get total row count.
cr.setprojection(projections.rowcount());

// to get average of a property.
cr.setprojection(projections.avg("salary"));

// to get distinct count of a property.
cr.setprojection(projections.countdistinct("firstname"));

// to get maximum of a property.
cr.setprojection(projections.max("salary"));

// to get minimum of a property.
cr.setprojection(projections.min("salary"));

// to get sum of a property.
cr.setprojection(projections.sum("salary"));

criteria queries 例子:
考虑下面的pojo类:

public class employee {
  private int id;
  private string firstname; 
  private string lastname;  
  private int salary; 

  public employee() {}
  public employee(string fname, string lname, int salary) {
   this.firstname = fname;
   this.lastname = lname;
   this.salary = salary;
  }
  public int getid() {
   return id;
  }
  public void setid( int id ) {
   this.id = id;
  }
  public string getfirstname() {
   return firstname;
  }
  public void setfirstname( string first_name ) {
   this.firstname = first_name;
  }
  public string getlastname() {
   return lastname;
  }
  public void setlastname( string last_name ) {
   this.lastname = last_name;
  }
  public int getsalary() {
   return salary;
  }
  public void setsalary( int salary ) {
   this.salary = salary;
  }
}

让我们创建下面的employee表来存储employee对象:

create table employee (
  id int not null auto_increment,
  first_name varchar(20) default null,
  last_name varchar(20) default null,
  salary   int default null,
  primary key (id)
);

以下将被映射文件。

<?xml version="1.0" encoding="utf-8"?>
<!doctype hibernate-mapping public 
 "-//hibernate/hibernate mapping dtd//en"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
  <class name="employee" table="employee">
   <meta attribute="class-description">
     this class contains the employee detail. 
   </meta>
   <id name="id" type="int" column="id">
     <generator class="native"/>
   </id>
   <property name="firstname" column="first_name" type="string"/>
   <property name="lastname" column="last_name" type="string"/>
   <property name="salary" column="salary" type="int"/>
  </class>
</hibernate-mapping>

最后,我们将创建应用程序类的main()方法来运行,我们将使用criteria查询的应用程序:

import java.util.list; 
import java.util.date;
import java.util.iterator; 
 
import org.hibernate.hibernateexception; 
import org.hibernate.session; 
import org.hibernate.transaction;
import org.hibernate.sessionfactory;
import org.hibernate.criteria;
import org.hibernate.criterion.restrictions;
import org.hibernate.criterion.projections;
import org.hibernate.cfg.configuration;

public class manageemployee {
  private static sessionfactory factory; 
  public static void main(string[] args) {
   try{
     factory = new configuration().configure().buildsessionfactory();
   }catch (throwable ex) { 
     system.err.println("failed to create sessionfactory object." + ex);
     throw new exceptionininitializererror(ex); 
   }
   manageemployee me = new manageemployee();

   /* add few employee records in database */
   integer empid1 = me.addemployee("zara", "ali", 2000);
   integer empid2 = me.addemployee("daisy", "das", 5000);
   integer empid3 = me.addemployee("john", "paul", 5000);
   integer empid4 = me.addemployee("mohd", "yasee", 3000);

   /* list down all the employees */
   me.listemployees();

   /* print total employee's count */
   me.countemployee();

   /* print toatl salary */
   me.totalsalary();
  }
  /* method to create an employee in the database */
  public integer addemployee(string fname, string lname, int salary){
   session session = factory.opensession();
   transaction tx = null;
   integer employeeid = null;
   try{
     tx = session.begintransaction();
     employee employee = new employee(fname, lname, salary);
     employeeid = (integer) session.save(employee); 
     tx.commit();
   }catch (hibernateexception e) {
     if (tx!=null) tx.rollback();
     e.printstacktrace(); 
   }finally {
     session.close(); 
   }
   return employeeid;
  }

  /* method to read all the employees having salary more than 2000 */
  public void listemployees( ){
   session session = factory.opensession();
   transaction tx = null;
   try{
     tx = session.begintransaction();
     criteria cr = session.createcriteria(employee.class);
     // add restriction.
     cr.add(restrictions.gt("salary", 2000));
     list employees = cr.list();

     for (iterator iterator = 
              employees.iterator(); iterator.hasnext();){
      employee employee = (employee) iterator.next(); 
      system.out.print("first name: " + employee.getfirstname()); 
      system.out.print(" last name: " + employee.getlastname()); 
      system.out.println(" salary: " + employee.getsalary()); 
     }
     tx.commit();
   }catch (hibernateexception e) {
     if (tx!=null) tx.rollback();
     e.printstacktrace(); 
   }finally {
     session.close(); 
   }
  }
  /* method to print total number of records */
  public void countemployee(){
   session session = factory.opensession();
   transaction tx = null;
   try{
     tx = session.begintransaction();
     criteria cr = session.createcriteria(employee.class);

     // to get total row count.
     cr.setprojection(projections.rowcount());
     list rowcount = cr.list();

     system.out.println("total coint: " + rowcount.get(0) );
     tx.commit();
   }catch (hibernateexception e) {
     if (tx!=null) tx.rollback();
     e.printstacktrace(); 
   }finally {
     session.close(); 
   }
  }
 /* method to print sum of salaries */
  public void totalsalary(){
   session session = factory.opensession();
   transaction tx = null;
   try{
     tx = session.begintransaction();
     criteria cr = session.createcriteria(employee.class);

     // to get total salary.
     cr.setprojection(projections.sum("salary"));
     list totalsalary = cr.list();

     system.out.println("total salary: " + totalsalary.get(0) );
     tx.commit();
   }catch (hibernateexception e) {
     if (tx!=null) tx.rollback();
     e.printstacktrace(); 
   }finally {
     session.close(); 
   }
  }
}

编译和执行:
下面是步骤来编译并运行上述应用程序。请确保您已在进行的编译和执行之前,适当地设置path和classpath。

  • 创建hibernate.cfg.xml配置文件中配置章节解释。
  • 创建employee.hbm.xml映射文件,如上图所示。
  • 创建employee.java源文件,如上图所示,并编译它。
  • 创建manageemployee.java源文件,如上图所示,并编译它。
  • 执行manageemployee二进制运行程序.

会得到以下结果,并记录将创建在employee表中。

$java manageemployee
.......various log messages will display here........

first name: daisy last name: das salary: 5000
first name: john last name: paul salary: 5000
first name: mohd last name: yasee salary: 3000
total coint: 4
total salary: 15000

如果检查employee表,它应该记录如下:

mysql> select * from employee;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 14 | zara    | ali    |  2000 |
| 15 | daisy   | das    |  5000 |
| 16 | john    | paul   |  5000 |
| 17 | mohd    | yasee   |  3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)