hibernate执行sql

Hibernate还支持使用SQL查询,使用SQL查询可以利用某些数据库的特性,或者用于将原有的JDBC应用迁移到Hibernate应用上。使用命名的SQL查询还可以将SQL语句放在配置文件中配置,从而提高程序的解耦,命名SQL查询还可以用于调用存储过程。

如果是一个新的应用,通常不要使用SQL查询。

SQL查询是通过SQLQuery接口来表示的,SQLQuery接口是Query接口的子接口,因此完全可以调用Query接口的方法:

   ● setFirstResult(),设置返回结果集的起始点。

   ● setMaxResults(),设置查询获取的最大记录数。

   ● list(),返回查询到的结果集。

但SQLQuery比Query多了两个重载的方法:

   ● addEntity,将查询到的记录与特定的实体关联。

   ● addScalar,将查询的记录关联成标量值。

执行SQL查询的步骤如下:

(1)获取Hibernate Session对象;

(2)编写SQL语句;

(3)以SQL语句作为参数,调用Session的createSQLQuery方法创建查询对象;

(4)如果SQL语句包含参数,调用Query的setXxx方法为参数赋值;

(5)调用SQLQuery对象的addEntity或addScalar方法将选出的结果与实体或标量值关联;

(6)调用Query的list方法返回查询的结果集。

看下面的SQL查询示例:

private void test()

{

    //获取Hibernate Session对象

    Session session = HibernateUtil.currentSession();

    //开始事务

    Transaction tx = session.beginTransaction();

    //编写SQL语句

    String sqlString = "select {s.*} from student s where s.name like '马军'";

    //以SQL语句创建SQLQuery对象

    List l = session.createSQLQuery(sqlString)

                    //将查询到的记录与特定实体关联起来

                    .addEntity("s",Student.class)

                    //返回全部的记录集

                    .list();

    //遍历结果集

    Iterator it = l.iterator();

    while (it.hasNext())

    {

        //因为将查询结果与Student类关联,因此返回的是Student集合

        Student s = (Student)it.next();

        Set enrolments = s.getEnrolments();

        Iterator iter = enrolments.iterator();

        while(iter.hasNext())

        {

            Enrolment e = (Enrolment)iter.next();

            System.out.println(e.getCourse().getName());

        }

    }

    //提交事务

    tx.commit();

    //关闭Session

    HibernateUtil.closeSession();

}

上面的示例显示了将查询记录关联成一个实体的示例。事实上,SQL查询也支持将查询结果转换成标量值,转换成标量值可以使用addScalar方法,如:

Double max = (Double) session.createSQLQuery("select max(cat.weight) as maxWeight from cats cat")

        .addScalar("maxWeight", Hibernate.DOUBLE);

        .uniqueResult();

使用SQL查询,如果需要将查询到的结果转换成特定实体,就要求为选出的字段命名别名。这别名不是随意命名的,而是以“/”实例名.属性名“/”的格式命名,例如:

//依次将多个选出的字段命名别名,命名别名时都以ss作为前缀,ss是关联实体的别名

String sqlStr = "select stu.studentId as {ss.studentNumber},"

        + "stu.name as {ss.name} from "

        + "student as stu where stu.name like '杨海华'";

List l = session.createSQLQuery(sqlStr)

            //将查询出的ss实例,关联到Student类

            .addEntity("ss",Student.class)

            .list();

在第一个示例中,以{s.*}代表该表的全部字段,且关联实例的别名也被指定为s。

注意:如果不使用{s.*}的形式,就可让实体别名和表别名互不相同。关联实体的类型时,被关联的类必须有对应的setter方法。

4.5.1 命名SQL查询

可以将SQL语句不放在程序中,而放在配置文件中,这种方式以松耦合的方式配置SQL语句,可以提高程序解耦。

在Hibernate的映射文件中定义查询名,然后确定查询所用的SQL语句,然后就可以直接调用该命名SQL查询。在这种情况下,不需要调用addEntity()方法,因为在配置命名SQL查询时,已经完成了查询结果与实体的关联。

下面是命名SQL查询的配置片段:

   

   

       

         SELECT {s.*}

        from student s WHERE s.name like'杨海华'

sql-query元素是hibernate-mapping元素的子元素。因此,sql-query定义的名可以直接通过Session访问,上面定义的mySqlQuery查询可以直接访问,下面是使用该命名SQL查询的示例代码:

private void testNamedSQl()

{

    //获取Hibernate Session对象

    Session session = HibernateUtil.currentSession();

    //开始事务

    Transaction tx = session.beginTransaction();

    //调用命名查询,直接返回结果

    List l = session.getNamedQuery("mySqlQuery")

                         .list();

    //遍历结果集

    Iterator it = l.iterator();

    while (it.hasNext())

    {

        //在定义SQL查询时,已经将结果集与Student类关联起来

        //因此,集合里的每个元素都是Student实例

        Student s = (Student)it.next();

        Set enrolments = s.getEnrolments();

        Iterator iter = enrolments.iterator();

        while(iter.hasNext())

        {

            Enrolment e = (Enrolment)iter.next();

            System.out.println("=====================================");

            System.out.println(e.getCourse().getName());

            System.out.println("=====================================");

        }

    }

    tx.commit();

    HibernateUtil.closeSession();

}

4.5.2 调用存储过程

Hibernate 3增加了存储过程的支持,该存储过程只能返回一个结果集。

下面是Oracle 9i的存储过程示例:

CREATE OR REPLACE FUNCTION selectAllEmployments

    RETURN SYS_REFCURSOR

AS

    st_cursor SYS_REFCURSOR;

BEGIN

    OPEN st_cursor FOR

SELECT EMPLOYEE, EMPLOYER,

STARTDATE, ENDDATE,

REGIONCODE, EID, VALUE, CURRENCY

FROM EMPLOYMENT;

      RETURN st_cursor;

END;

如果需要使用该存储过程,可以先将其定义成命名SQL查询,例如:

   

   

       

       

       

       

       

       

       

       

       

           

           

           

       

   

    { ? = call selectAllEmployments() }

调用存储过程还有如下需要注意的地方:

   ● 因为存储过程本身完成了查询的全部操作,所以调用存储过程进行的查询无法使用setFirstResult()/setMaxResults()进行分页。

   ● 存储过程只能返回一个结果集,如果存储过程返回多个结果集,Hibernate将仅处理第一个结果集,其他将被丢弃。

   ● 如果在存储过程里设定SET NOCOUNT ON,将有更好的性能表现。当然也可以没有该设定。


1.执行sql,返回一个结果集,适用查询一个字段并返回一条记录 

Java代码   收藏代码
  1. public Long findSeqTbTest() {  
  2.     String sql = "select SEQ_TB_TEST.nextval from dual";  
  3.     SQLQuery query = this.getSession().createSQLQuery(sql);  
  4.     String str = query.uniqueResult().toString();  
  5.     return Long.valueOf(str);  
  6. }  

Java代码   收藏代码
  1. //获取表中最小的id  
  2. String sql = "select min(a.employeeid) from Emplyees a";  
  3. Long id = (Long) session.createQuery(sql).uniqueResult();  
  4.   
  5. //获取数据库时间mysql  
  6. String sql = "select now() from dual";  
  7. String time =  session.createSQLQuery(sql).uniqueResult().toString();  


2.删除、更新等操作,这里参数是从0开始的 
Java代码   收藏代码
  1. public void deleteTbTest(Long id) {  
  2.     String hql = "DELETE FROM TbTest WHERE ID = ?";  
  3.     this.getSession().createQuery(hql).setLong(0, id).executeUpdate();  
  4. }  

Java代码   收藏代码
  1. public void updateTbTest(Date date, boolean flag) {  
  2.     String sql = "update tb_test set t_name=? where t_status!=1 and t_date" + (flag ? " : "=?");  
  3.     SQLQuery query = this.getSession().createSQLQuery(sql);  
  4.     query.setString(0,flag ? "hello""hi").setDate(1, date).executeUpdate();  
  5. }  


3.执行sql,查询单表中多条数据 
Java代码   收藏代码
  1. //尽量避免适用"*"  
  2. String sql = "select * from employee e where e.valid=1 and not exists (select employeeid from attendance a where a.employeeid=e.employeeid and a.date = ?)";  
  3. SQLQuery query = getSession().createSQLQuery(sql);  
  4. query.addEntity(Employee.class).setDate(0, day);  
  5. List retList = query.list();  


4.查询多表 
Java代码   收藏代码
  1. String hql = "select new map(dept.deptID as deptID,dept.depNo as deptNo,dept.deptName as deptName,emp.empName as empName,emp.empID as empID,emp.empAge as age,emp.empNo as empNo) from Department dept ,Employee emp where dept.depID = emp.depID and emp.empName = ? and emp.sex = ?";  
  2. return getHibernateTemplate().find(hql, new Object[] { name, sex });  

每个字段都保存在map中(key是字段名,value是此字段的值如:[{empID=1,empName=leona,...},...]) 

5.查询多表 
Java代码   收藏代码
  1. String sql = "select dept.deptID as deptID,dept.depNo as deptNo,dept.deptName as deptName,emp.empName as empName,emp.empID as empID,emp.empAge as age,emp.empNo as empNo,emp.birthday as birthday from Employee emp LEFT JOIN Department dept on dept.depID = emp.depID where empName = ?";  
  2.         return (Listthis.getSession()  
  3.             .createSQLQuery(sql)  
  4.             .addScalar("deptID", Hibernate.STRING)  
  5.             .addScalar("deptNo", Hibernate.STRING)  
  6.             .addScalar("deptName", Hibernate.STRING)  
  7.             .addScalar("empName", Hibernate.STRING)  
  8.             .addScalar("empID", Hibernate.STRING)  
  9.             .addScalar("age", Hibernate.LONG)  
  10.             .addScalar("birthday", Hibernate.DATE)  
  11.             .addScalar("empNo", Hibernate.STRING)  
  12.             .setString(0, empName)  
  13.             // 将结果集映射为EmpBean对象  
  14.             .setResultTransformer(  
  15.                     Transformers.aliasToBean(EmpBean.class))  
  16.             .list();  


String hql = "from Attendance att where att.employeeid = ? and att.date =? "; 
List list = this.getHibernateTemplate().find(hql, 
new Object[] { employeeid, workDay }); 
if (null != list && !list.isEmpty()) { 
return list.get(0); 



String queryString = "FROM Attendance a WHERE a.employeeid=? AND DATE_FORMAT(a.date,'%Y-%m')=DATE_FORMAT(?,'%Y-%m') ORDER BY a.teamname"; 
Query queryObject = getSession(). createQuery(queryString); 
queryObject.setParameter(0, id); 
queryObject.setParameter(1, date); 
return queryObject.list(); 

Session session = getSession(); 
session.clear(); 
getSession().saveOrUpdate(transientInstance); 

startBatch()的用法 
public class LocalDaoImpl extends SqlMapClientDaoSupport implements LocalDao { 

    public void insertBuNaTaxBatLst(final PaginatedList list) 
    { 
         getSqlMapClientTemplate().execute(new SqlMapClientCallback() { 
                public Object doInSqlMapClient(SqlMapExecutor executor) 
                        throws SQLException { 
                    executor.startBatch(); 
                    // do some iBatis operations here 
                    for(int i=0,count=list.size();i                     {    
                        executor.insert("insertBuNaTaxBatLst", list.get(i)); 
                        if (i % 50 == 0) { 
                            System.out.println("----" + i);//没有意义只为测试 
                        } 
                    } 
                    executor.executeBatch(); 
                    return null; 
                } 
            }); 
    } 

你可能感兴趣的:(Hibernate)