Hibernate查漏补缺

查漏补缺

前不久整理了下Hibernate,发现没有全面的整理.这次就来个大扫除吧. 废话不多说,进入正题.

C3p0连接池及log4j日志配置

  • c3p0
    导包->配置hbm.cfg.xml文件

  • log4j 导包->配置log4j.properties文件

hbm2ddk.auto属性配置

  • create(每次都创建表,也就是正向生成)
    每次创建SessionFactory,根据实体类自动创建表
  • update(修改过后才创建表)
    只有在实体类和orm文件修改时,才修改表结构.

动态插入,动态更新

  • dynmic-insert"true|false(默认值)"
    默认为false 实体的属性为null时,生成的sql语句,也会插入null. 为true时,实体的属性为null时,生成的sql语句不会插入null列的内容,会自定插入数据库default默认值

  • dynamic-update="true|false(默认值) 动态更新:当一对象的属性没有发生改变时,Hibernate生成的Update语句中就不会出现对应的字段的内容。用来提高效率

类级别的延迟加载

  • < class lazy="true|false">
    true:表示延迟加载
    false: 表示不延迟加载
    延迟加载:不用不查,用时再查。

当使用load方法加载对象时,不进行数据库查询的操作,只有当使用到非主键属性时,Hibernate才会进行数据库的查询操作。

  • session对象的查询的方法两个:get和load

1 get方法:不参考类级别的lazy属性。直接使用立即加载查询类对象。
2 load方法:参考类级别的lazy属性的设置。获得的是代理对象,延迟加载要在同一个session对象,并且session对象没有关闭

openSession,getcurrentSession的区别

  • openSession

openSession每次线程都会创建一个新session

  • getcurrentSession

从当前线程获取session....事务结束,session自动关闭.hibernate使用这个时,必须要在Hiberna中配置.Spring里工厂里可以直接使用,不需要配置

load和get的区别

加载方式: get立即加载,load延迟加载.
返回类型 一个返回真实对象. 一个返回代理对象
查询无结果时: 一个返回null 一个返回代理对象

     唯一id主键------- session上下文------ 与数据库相关联  
瞬时状态   有             无               无 
持久状态   有             有               有       
托管状态   有             无               有

HQL语句

Query接口中常用的方法
1 list():返回加载的对象的集合。
2 setXXX(int 参数索引,参数的值):给HQL语句中的参数赋值
3 setXXX(String 参数名称,参数的值):给HQL语句中的参数赋值
4 setProperties(Map):给HQL语句中的参数赋值
5 setProperties(Object):给HQL语句中的参数赋值
6 uniqueResult():返回一条查询结构时使用的方法。返回一个对象。
7 query.setFirstResult(0);//设置查询的第一条记录的索引位置
8 query.setMaxResults(5);//设置查询的记录数量

利用Query接口操作对象,可以用占位符?,也可以用:参数名
增:不支持hql语句
删:delete 对象 where 对象.id query.executeUpdate()
改:update 对象 set 对象.列 where 对象.id象.idquery.executeUpdate()
查:select new Map(username as name,password as pwd)query.List()

HQL查询一些注意事项
  • 1.投影查询的返回结果类型:
    不能用select *
    select goodname,goodsid from goods;

Query.list返回的对象种类:

 List<object[]>(多行多列)      
 List<object>(多行一列)     
 Object[](一行多列)      
 Object(一行一列)       
  • 2.可以使用类对象来接收投影查询的结果.前提要有一个格式匹配的构造方法
String hql="select new  Goods(goodid,goodsName,goodsPrice) from com.no4.domain.Goods"  
 List<Goods> goodsList=query.list();

上面的情况无论有几行几列,都会返回一个List

  • 3.List里面可以放一个Map.List等集合遍历集合得到值.
    里面还可以支持max count各种函数
分页函数
 query.setFirstResult();//查询第一条记录的索引位置  
 query.setMaxResults(5);//每页条数
条件hql

1.?
2.:参数名(建议使用)

  • 给单个条件复制: query.setXXX(1,value) query.setXXX("test",value)

  • 给多个条件赋值:query.setproperties(map); query.setproperties(object);

Criteria

QBC以及QBE(纯面向对象的查询)

  • Criteria本身只是个查询容器,Cretiria.add增加条件.
//Criteria对象的创建
         Criteria criteria=session.createCriteria(Goods.class);

         List<Goods> list=criteria.list();
                 for (Goods goods : list) {
                    System.out.println(goods.getGoodsName());
                }
     }

查询所有该持久化类,并且遍历.增加条件

criteria.add(Restrictions.gt("goodsPrice", 500.0));  
条件与的三种方式:

1.直接在后面add

criteria.add(Restrictions.gt("goodsPrice", 500.0)).add(Restrictions.lt("goodsPrice", 1000.0));  

2.Restrictions.and

 Criterion criterion=Restrictions.gt("goodsPrice", 500.0);
 Criterion criterion2=Restrictions.lt("goodsPrice", 1000.0);
 Criterion criterion3=Restrictions.and(criterion,criterion2);
 criteria.add(criterion3);

3.推荐用第三种

Criterion criterion = Restrictions.gt("goodsPrice", 500.0);  
Criterion criterion2 = Restrictions.lt("goodsPrice", 1000.0);  
Conjunction conjunction = new Conjunction();  
conjunction.add(criterion);//这个条件和下面那个条件是都没影响  
conjunction.add(criterion2);  
criteria.add(conjunction);  
条件或的方式

1.Restrictions.or

  Criterion criterion1 = Restrictions.gt("goodsPrice", 2000.0);
  Criterion criterion2 = Restrictions.lt("goodsnum", 100);
  Criterion criterion3 = Restrictions.or(criterion1, criterion2);
  criteria.add(criterion3);

2.Restrictions.djsjunction

 Criterion criterion1 = Restrictions.gt("goodsPrice", 2000.0);
 Criterion criterion2 = Restrictions.lt("goodsnum", 90);
 criteria.add(Restrictions.disjunction().add(criterion1).add(criterion2));
模糊查询
  criteria.add(Restrictions.like("goodsName", "商品", MatchMode.ANYWHERE));
MatchMode.START:字符串在最前面的位置.相当于"like 'key%'"  
MatchMode.END:字符串在最后面的位置.相当于"like '%key'"  
MatchMode.ANYWHERE:字符串在中间匹配.相当于"like '%key%'"  
MatchMode.EXACT:字符串精确匹配.相当于"like 'key'"  
排序
criteria.addOrder(Order.desc("goodsPrice"));//降序  
criteria.addOrder(Order.asc("goodsPrice"));//升序  
分页
   criteria.setMaxResults(5).setFirstResult(0);
   每页5个,从第一页开始.
投影查询

投影查询:只查询某几列的时候

  • 单属性投影
   criteria.setProjection(Projections.property("goodsName"));    
     List<String> list=criteria.list();
  • 多属性投影
 criteria.setProjection(Projections.projectionList()
.add(Projections.property("goodsName")).add(Projections.property("goodsPrice"))
---------------------------------------------------
多属性投影查询可以设置为Map集合。返回的集合的泛型是一个Map对象
  criteria.setProjection(Projections.projectionList()
  .add(Projections.property("goodsName"), "name")
  .add(Projections.property("goodsPrice"), "price")
  .add(Projections.property("goodsnum"), "num"));
        // 将多属性投影查询映射成一个Map对象
        criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);
        // 多属性投影查询时返回的集合的泛型是一个Map
        List<Map<String, Object>> list = criteria.list();
        for (Map<String, Object> map : list) {
            System.out.println(map.get("name") + ":" 
                    + map.get("price") + ":"
                    + map.get("num"));
        }
支持聚合函数
一旦使用聚合函数,一定要投影查询.
select count(*),max from goods.

              //查询一列时
           criteria.setProjection(
            Projections.rowCount()
                    );
添加多个聚合函数..要用投影查询
      criteria.setProjection(Projections.projectionList()
        .add(Projections.sum("detailnum"), "sum")
            .add(Projections.sum("detailprice"), "sumprice"));
        criteria.setResultTransformer(criteria.ALIAS_TO_ENTITY_MAP);
        Map<String, Object> map=(Map<String, Object>)criteria.uniqueResult();
        System.out.println(map.get("sum"));
        System.out.println(map.get("sumprice"));
分组

add(Projections.groupProperty("types"),会按照类型分组.得到一个多行多列的值.也就是List

criteria.setProjection(Projections.projectionList()  
                .add(Projections.property("types"),"type")
                .add(Projections.rowCount(),"count")
                .add(Projections.sum("goodsnum"),"num") 
                .add(Projections.groupProperty("types"))
                );
去除重复

criteria.setResultTransformer(Criteria.DISTINCTROOTENTITY);

关联关系查询

在使用QBC查询关联关系对象时,两种方式:

本来要查询的hql语句//多对一查询关系
hql : from Goods g where g.types.typename = '家用电器' and goodsPrice > 1000 ;  
  • 1.使用一个关联关系对象的新的查询 (criteria.createCriteria("types"))使用新查询时,多个条件之间有前后顺序要求。
Criteria criteria = session.createCriteria(Goods.class,"g");  
        criteria
            .add(Restrictions.gt("goodsPrice", 1000.0))
            .createCriteria("types")
            .add(Restrictions.eq("typename", "家用电器"))
            ;

        List<Goods> goodsList = criteria.list();
  • 2.给一个关联关系对象创建别名 (criteria.createAlias("g.types","y"))使用别名,多个条件之间是没前后顺序要求的。
Criteria criteria = session.createCriteria(Goods.class,"g");  
        criteria.createAlias("g.types", "t");//为关联关系对象创建别名为"t"
       (如果是一对多关系时,这个t就是迭代types字元素!!!!!)

        //增加关联关系的条件 : 类型名称为“家用电器” . 为关联关系对象加别名
        criteria.add(Restrictions.eq("t.typename", "家用电器"));
        criteria.add(Restrictions.gt("g.goodsPrice", 1000.0));
        List<Goods> goodsList = criteria.list();
关联关系设置连接方式(左/右/内)

左连接:左边可以为空,右反之.内都不能为空.

import org.hibernate.sql.JoinType;  
criteria.createAlias("goodses", "g" , JoinType.LEFT_OUTER_JOIN);  

QBE

QBE按模板查询,QBE只能支持比较,相等。(很鸡肋,没啥太大用)
··· //按goods这个类的模板比较 Goods goods=new Goods();
goods.setName("asda");
goods.setNumber("asd");
criteria.add(Example.create(goods));
List goods=criteria.list();
···

SQL原生语句

麻烦,也基本不用

String sql = "select * from goods";  
        SQLQuery sqlQuery = session.createSQLQuery(sql);
        sqlQuery.addEntity(Goods.class);
        List<Goods> goodsList = sqlQuery.list();

kxind

性别:男. 敢于尝试 爱折腾的死宅程序猿. https://github.com/kxinds