暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Hibernate查询

陌淮缘 2017-09-26
242

1.Hibernate查询方式

   1.get|load(class,id):OID查询

   2.HQL(Hibernate Query Lanage):HQL查询

   3.QBC(Query By Criteria):Criteria查询

   4.原生SQL查询(Native Sql):使用Hibernate来执行sql语句

   5.命名查询:在映射文件中定义字符串形式的查询语句

2.Hibernate查询操作

     2.1、HQL:(update delete select)

     HQL查询示例:

     1.获得Session

     Session session = HibernateSessionFactory.getSession();

     2.编写hql

     String hql = "from Dept";

     3.通过Session创建Query对象

     Query query = session.createQuery(hql);

     4.通过Query对象执行hql查询

     List<Dept> list = query.list();

     for(Dept dept:list){

     System.out.println(dept.getDname());

     }

     5.关闭Session

     session.close();

     eg:

     1.不带条件查询

     String hql = "from Book"

     Query query = session.createQuery(hql);

     2.带条件查询

     String hql = "from Book where bookName=?"

     Query query = session.createQuery(hql);

     query.setString(0,"Oracle");

     query.setParameter(0,"Oracle");

     3.投影查询

     3.1:只查询对象的某个属性 封装指定类型集合

     Query query = session.createQuery("select name from Users");

     List<String> names = query.list();

     3.2:查询对象的多个属性  封装Object数组集合

     Query query = session.createQuery("select name,pwd from Users");

     List<Object[]> users = query.list();

     3.3:查询对象的多个属性 封装成对象 在pojo中提供相应的构造函数

     Query query = session.createQuery("select new Users(name,pwd) from Users");

     List<Users> users = query.list();

     4、查询绑定参数的方式

      按参数位置绑定  

     根据数据类型使用set方法(下标,参数值)

      按参数名绑定

     使用setParameter(参数名,参数值)

      使用对象作为方法参数进行查询

     setProperties(对象名);

     连接查询

     迫切内连接: 特点是:不返回左表不满足条件

     eg:FROM  Department d INNER JOIN FETCH  d.emps

     INNER JOIN FETCH 关键字表示迫切内连接, 也可以省略 INNER 关键字

     list() 方法返回的集合中存放Department对象的引用, 每个Department对象的 Employee 集合都被初始化, 存放所有关联的 Employee 对象  

     内连接:

     eg:FROM  Department d INNER JOIN  d.emps

     INNER JOIN 关键字表示内连接, 也可以省略 INNER 关键字

     list() 方法的集合中存放的每个元素对应查询结果的一条记录, 每个元素都是对象数组类型

     如果希望 list() 方法的返回的集合仅包含 Department  对象, 可以在 HQL 查询语句中使用 SELECT 关键字

     迫切左外连接: 特点是:如果左表有不满足条件的,也返回左表不满足条件

     1. LEFT JOIN FETCH 关键字表示迫切左外连接检索策略.

     2. list() 方法返回的集合中存放实体对象的引用, 每个 Department 对象关联的 Employee 集合都被初始化,存放所有关联的 Employee 的实体对象.  

     3. 查询结果中可能会包含重复元素, 可以通过一个 HashSet 来过滤重复元素

     去重:

     方法一:使用 distinct

     String hql  = "SELECT DISTINCT d FROM  Department d LEFT JOIN FETCH d.emps ";

     Query query = session.createQuery(hql);

      

     List<Department> depts = query.list();

     System.out.println(depts.size());

     方法二

       String hql  = "FROM  Department d LEFT JOIN FETCH d.emps ";

       Query query = session.createQuery(hql);

       List<Department> depts = query.list();

      

       depts = new ArrayList<>(new LinkedHashSet(depts));

       System.out.println(depts.size());

       for(Department dept:depts){

       System.out.println(dept.getName() + "--" + dept.getEmps().size() );

       }

     左外连接:  

     1. LEFT JOIN 关键字表示左外连接查询.  

     2. list() 方法返回的集合中存放的是对象数组类型

     3. 根据配置文件来决定 Employee 集合的检索策略.  

     4. 如果希望 list() 方法返回的集合中仅包含 Department 对象,  可以在HQL 查询语句中使用 SELECT 关键字

     这样的语句查询的结果有重复:

     String hql = "FROM Department d LEFT JOIN d.emps";

     Query query = session.createQuery(hql);

    

     List<Object[]> results = query.list();

     System.out.println(results.size());

     去重:

     仅能使用  distinct 的方法去除重复

     String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN d.emps";

     Query query = session.createQuery(hql);

      

     List<Department> depts = query.list();

     System.out.println(depts.size());

     for(Department dept:depts){

     System.out.println(dept.getName() + dept.getEmps().size());

     }

     注意:

     如果要查询表中所有字段的信息,那么hql语句中不使用

     String hql = "from Book"    <==>

     String hql = "select bookId,bookName,author,price from Book";

     String hql = "select bookName,author from Book";

     如果只查询某一列的值,那么集合中对应的就不再是一个对象了

     List<String> list = query.list(hql);

     如果查询某几列的数据,那么集合中对应的每个元素对应的就是一个数组相同数据类型使用String[] 或其他数据类型数组,不同数据类型使用Object[], 模糊查询 排序都不变,查询不需要发起事务,修改需要发起事务query.executeUpdate(); 可以自行修改删除

     HQL分页

     query.setFirstResult();    设置当前页起始行索引

     query.setMaxResults();     设置每页记录条数

     具体查询一条数据可以使用uniqueResult();

     Book book = (Book)uniqueResult();    

   2.2.Criteria查询:

      Criteria查询示例:

     1.获得Session

     Session session = HibernateSessionFactory.getSession();

     2.通过session创建Criteria对象

     Criteria criteria = session.createCriteria(Class arg);

     eg:Criteria criteria = session.createCriteria(Book.class);

     Criteria criteria = session.createCriteria(String arg);

     eg:Criteria criteria = session.createCriteria("com.entity.Book");

     3.通过Criteria对象执行查询

     List<Book> list = criteria.list();

     4.关闭Session

     session.close();  

           条件查询

     //比较运算

     cri.add(Restrictions.eq("bookName","sql")); //eq等于 le小于等于 lt小于 ge大于等于 gt大于

     //模糊查询

     cri.add(Restrictions.like("bookName","%a%"));

     //范围运算

     Restrictions.in( )

     //逻辑运算

     Restrictions.and( )

     cri.add(Restrictions.or(Restrictions.eq("bookName","sql"),Expression.eq("price",50)));

     criteria.addOrder(Order.desc("price"));

     集合运算

     Restrictions.isEmpty( )

     排序

     List<Emp> list = session.createCriteria(Emp.class)

     .add(Restrictions.gt("salary", 4000D))

     .addOrder(Order.asc("salary"))

     .addOrder(Order.desc("empNo")).list();

     分页:

     criteria.setFirstResult();    设置当前页起始行索引

     criteria.setMaxResults();     设置每页记录条数

     List<Emp> list = session.createCriteria(Emp.class)

     .add(Restrictions.isNotNull("salary"))

     .addOrder(Order.desc("salary"))

     .setFirstResult(0)

     .setMaxResults(2).list();

     查询唯一对象:

     Emp emp = (Emp) session.createCriteria(Emp.class)

     .add(Restrictions.isNotNull("salary"))

     .addOrder(Order.desc("salary"))

     .setMaxResults(1)

     .uniqueResult();

     关联:

     方式一:

     List<Emp> list = session.createCriteria(Emp.class)

     .add(Restrictions.ilike("empName", "a", MatchMode.ANYWHERE))

     .createCriteria("dept")

     .add(Restrictions.eq("deptName", "财务部").ignoreCase()) .list();

     方式二:

     List<Emp> list = session.createCriteria(Emp.class, "e")

     .createAlias("dept", "d")

     .add(Restrictions.ilike("e.empName", "a",MatchMode.ANYWHERE))

     .add(Restrictions.eq("d.deptName", "财务部").ignoreCase()).list();

     投影:

     List<String> list = session.createCriteria(Dept.class).setProjection(Property.forName("deptName")).list();

     List<Object[]> list = session.createCriteria(Emp.class)

     .setProjection(Projections.projectionList().add(Property.forName("empName")).add(Property.forName("hiredate"))).list();

     分组、聚合函数:

     List<Object[]> list = session.createCriteria(Emp.class, "e").createAlias("e.dept", "d")

     .setProjection(Projections.projectionList().add(Projections.groupProperty("d.deptName"))

     .add(Projections.avg("e.salary")).add(Projections.max("e.salary")).add(Projections.min("e.salary"))).list();

     for (Object[] obj : list) {

     System.out.println(obj[0] + ","+obj[1]+ ","+obj[2]+ ","+obj[3]);

     }

     DetachedCriteria查询:

     DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Emp.class, "e").createAlias("e.dept", "d")

     .add(Restrictions.eq("d.deptName", "财务部").ignoreCase()).add(Restrictions.ilike("e.empName", "a",MatchMode.ANYWHERE));

     List<Emp> list = detachedCriteria.getExecutableCriteria(session).list();

     常见问题:

     1.Restrictions类的作用是什么?

     2.Criteria接口是否有uniqueResult()方法?

     3.Criteria查询如何对查询结果排序?

     4.setFirstResult()方法的作用是什么?

     5.Criteria查询如何实现关联?

     6.groupProperty()方法的作用是什么?

     7.DetachedCriteria有什么作用?

     HQL和QBC的区别:

     1.HQL需要sql基础 可以执行查询 修改 删除

     2.HQL查询更加灵活方便

     3.在HQL中可以使用子查询 QBC只能进行一些简单的查询

     4.Criteria查询和HQL查询都支持连接查询,需要注意的是Criteria只支持内连接和迫切左外连接。

   2.3.原生SQL查询:

     原生SQL查询示例:

            1.获得Session

                Session session = HibernateSessionFactory.getSession();

            2.编写SQL语句

                String sql = "select  from EMP where ENAME like :ename and JOB = :job";

            3.通过session创建SQLQuery对象    

     Query query = session.createSQLQuery(sql).setString("ename", "%e%").setString("job", "ENGINEER");

                List<Object[]> list = query.list();

            4.通过SQLQuery对象执行sql查询

                List<Object[]> list = query.list();

            5.关闭Session

                session.close();

     注意:

     List cats = sess.createSQLQuery( " select  from cats " ).addEntity(Cat. class ).list();

     这个查询指定了:SQL查询字符串、查询返回的实体

     结果集字段名被假设为与映射文件中指明的字段名相同。对于连接了多个表的查询,这就可能造成问题,因为可能在多个表中出现同样名字的字段。下面的方法就可以避免字段名重复的问题:

     List cats = sess.createSQLQuery( " select {cat.} from cats cat " ).addEntity( " cat " , Cat. class ).list();

     这个查询指定了:SQL查询语句,它带一个占位符,可以让Hibernate使用字段的别名.查询返回的实体,和它的SQL表的别名

     addEntity()方法将SQL表的别名和实体类联系起来,并且确定查询结果集的形态。

     addJoin()方法可以被用于载入其他的实体和集合的关联.

     List cats = sess.createSQLQuery(" select {cat.}, {kitten.} from cats cat, cats kitten where kitten.mother = cat.id " )

     .addEntity( " cat " , Cat. class )

     .addJoin( " kitten " , " cat.kittens " )

     .list();

     原生的SQL查询可能返回一个简单的标量值或者一个标量和实体的结合体。

     HQL和SQL查询的区别:

     HQL查询的是类 得到的是对象 可以进行强制转换

     SQL查询的是表中的记录 不能进行强制转换

     如果想进行强转 需要进行表和类的绑定

     sqlQuery.addEntity("Book",Book.class); 

  2.4.命名查询

       HQL语句的命名查询:

      xxx.hbm.xml:

<query name="findEmpByJob">

<![CDATA[from Emp e where e.job = :job]]>

</query>

      Test.java:

           List<Emp> list = session.getNamedQuery("findEmpByJob").setString("job", "ENGINEER").list();

       原生SQL语句的命名查询:

      xxx.hbm.xml:

<sql-query name="selectEmpByJobJoinDept">

<return alias="e" class="cn.jbit.hibernatedemo.entity.Emp"/>

<return-join alias="d" property="e.dept"></return-join>

select {e.},{d.} from EMP e join DEPT d on d.DEPTNO=e.DEPTNO where e.JOB = :job

</sql-query>

       Test.java:

           List<Object[]> list = session.getNamedQuery("selectEmpByJobJoinDept").setString("job", "ENGINEER").list();

           Emp emp = null;

           Dept dept = null;

           for (Object[] obj : list) {

               System.out.println(obj[0] + "," + obj[1]);

               emp = (Emp) obj[0];

               dept = (Dept) obj[1];

               System.out.println(emp.getEmpName() + "," + dept.getDeptName());

           }

     注意:

     <return/>:将查询结果转换成持久化实体

            <return-join/>:预加载持久化实体的关联实体

     <return-scalar/>:将查询的数据列转换成标量值

     <sql-query name="sqlquery">  

     <!-- 将p别名转换为Person实体 -->  

     <return alias="p" class="Person" />  

     <!-- 将e别名转换成Event实体 -->  

     <return alias="e" class="MyEvent" />  

     <!-- 指定将person_inf表的name属性列作为标量值返回-->  

     <return-scalar column="p.name" type="string"/>  

     select p.,e. from person_inf as p,event_inf as e where p.person_id = e.person_id and p.age=:age  

     </sql-query>  

     eg:

     List list = session.getNamedQuery("sqlquery")  

     .setInteger("age", 30).list();  

     for(Iterator iterator = list.iterator();iterator.hasNext();){  

     //每个集合元素都是Person、MyEvent所组成的数组  

     Object[] objects = (Object[]) iterator.next();  

     Person person = (Person) objects[0];  

     MyEvent event = (MyEvent) objects[1];  

     System.out.println("person_id="+person.getId()+" person_name="+person.getName()+" title="+event.getTitle());  

     }

文章转载自陌淮缘,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论