1. HQL查询
<span style="font-size:14px;">// 1. 聚合函数统计 // 需求: 统计总人数! //Query q = session.createQuery("select count(*) from User"); //Long count = (Long) q.uniqueResult(); // 返回结果的第一行; 如果结果有多行,报错! /* * 2. 分组查询、分组后筛选 * -- 需求: 统计每个用户的地址的个数! 显示地址数目>3的用户 SELECT user_id, COUNT(*) FROM t_address GROUP BY user_id */ //Query q = session.createQuery("select d.user, count(*) from Address d group by d.user having count(*) >3"); /* * 3.1 内连接 * -- 需求:显示地址信息、用户名称 SSELECT * FROM t_address d INNER JOIN t_user u ON d.user_id=u.id */ //Query q = session.createQuery("from Address d inner join d.user"); //结果集是Object类型,结果集里的数据都是一个Object数组,Object数组里才是两个表对应的实体类对象. // fetch 把“右表”的数据,填充到“左表!” //结果集是Object类型,但结果集里的数据是Address(from后面的)类型,Address里包含本身的字段和user(连接表的实体对象)对象 Query q = session.createQuery("from Address d inner join fetch d.user"); //4. 左/右连接 /* SELECT u.*,d.address FROM t_user u LEFT JOIN t_address d ON d.user_id=u.id */ //Query q = session.createQuery("from User u left join u.addresses ") </span>
2. Criteria查询
<span style="font-size:14px;">//Query对象有的方法,Criteria基本都有. //查询对象/表 Criteria c =session.createCriteria(User.class); //1.添加条件 c.add(Restrictions.idEq(1)); //根据主键查询! c.add(Restrictions.eq("name", "副班2")); // 等值查询,对象的属性名与对应的值 // 2.添加条件 , 用map封装 Map<String,Object> map = new HashMap<String,Object>(); map.put("id", 1); // map的key表示对象的属性! map.put("name", "副班1"); //两个条件关系为AND c.add(Restrictions.allEq(map)); // 3.Example查询 : 把对象属性作为条件! User user = new User(); // user.setId(1000); 不会作为查询条件! user.setName("副班1"); user.setAge(25); user.setSex('女'); //Criteria c =session.createCriteria(User.class); // 把对象的属性作为查询条件! c.add(Example.create(user));</span>
3. 本地SQL查询
Hibernate也提供了对原始的sql语句的支持.以提供hibernate的HQL的不足.缺点:不能跨数据库平台,而hql或Criteria 可以.如果换了数据库,需要修改sql语句,改代码.// 获取本地sql查询接口SQLQuery q = session.createSQLQuery("SELECT * FROM t_address d");// 查询返回的是:List<Address>, 如果希望把每一条记录封装为对象: List<Address>;// 可以这样做q.addEntity(Address.class);// Address对象必须映射!
4. Hibernate对连接池支持
<span style="font-size:14px;">查找文档hibernate.properties,里面提供了支持的连接池的连接配置.
如:
###########################
### C3P0 Connection Pool### hibernate对c3p0连接池的支持
###########################
#hibernate.c3p0.max_size 2
#hibernate.c3p0.min_size 2
#hibernate.c3p0.timeout 5000
#hibernate.c3p0.max_statements 100
#hibernate.c3p0.idle_test_period 3000
#hibernate.c3p0.acquire_increment 2
#hibernate.c3p0.validate false
连接池驱动类 (CombopooledDataSource)
#hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider
====<!-- C3P0连接池的配置 -->
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
<!-- 连接的最大数目 -->
<property name="hibernate.c3p0.max_size">2</property>
<!-- 最小连接数 -->
<property name="hibernate.c3p0.min_size">2</property>
<!-- 连接超时时间! -->
<property name="hibernate.c3p0.timeout">5000</property>
<!-- 一次最多执行的sql的个数! -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- 测试时间 -->
<property name="hibernate.c3p0.idle_test_period">3000</property>
<!-- 连接增量 -->
<property name="hibernate.c3p0.acquire_increment">2</property></span>
5. session的创建方式
1). openSession()每次都新创建一个新的session.1. 查询可以不开启事务.
2).getCurrentSession()
使用前必须配置:<property name="hibernate.current_session_context_class">thread</property>创建流程:
a. 先从当前线程获取sesison;b. 没有获取到 ,就创建session: 调用:openSession()c. 然后把当前创建的session绑定到当前线程上;d. 再次获取,
从当前线程上获取session.
注意:
1. 提交事务,会自动关闭session.2. 查询也需要开启事务.
6. 二级缓存
<span style="font-size:14px;">查看hibernate.properties 文档 ########################## ### Second-level Cache ### ########################## ## disable the second-level cache 二级缓存默认没有开启,如果需要用,要手动设置为true! #hibernate.cache.use_second_level_cache false 二级缓存默认没有开启,如果需要用,要手动设置为true! ## enable the query cache #hibernate.cache.use_query_cache true 是否开启查询缓存! ## store the second-level cache entries in a more human-friendly format #hibernate.cache.use_structured_entries true ## choose a cache implementation 二级缓存框架的实现(hibernate默认支持的几种插件!) #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider(额外引入jar包!) #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默认实现! #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider(额外引入jar包!) #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider ====hibernate.cfg.xml配置二级缓存 <!-- 二级缓存配置: 1) 开启二级缓存: hibernate.cache.use_second_level_cache 2) 指定二级缓存框架实现 :hibernate.cache.provider_class 3) 指定哪些类,需要加入二级缓存! : <class-cache ../> 4) 集合缓存 <collection-cache../> 注意:集合缓存,集合的缓存的对象,也要加入二级缓存! 5) 缓存策略 usage="read-only" 只读; 二级缓存的数据是只读的! usage="read-write" 读写 nonstrict-read-write 非严格的读写(不会对数据锁定) transactional 基于事务的二级缓存(暂不支持) 6) 查询缓存 hibernate.cache.use_query_cache true --> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property> <property name="hibernate.cache.use_query_cache">true</property> <class-cache usage="read-write" class="cn.hibernate.c_second_cache.User"/> <class-cache usage="read-only" class="cn.hibernate.c_second_cache.Address"/> <collection-cache usage="read-only" collection="cn.hibernate.c_second_cache.User.addresses"/></span>
===== 面试题: 更新数据是否会通知一级缓存?二级缓存?
---> 更新数据,不会通知一级缓存.
---> 更新数据,二级缓存获取的数据是最新的.
* 先更新数据,再从二级缓存获取,此时会对比如果二级缓存对象数据与数据库不一致,就重新查询.
7. OSIV开发模式
hibernate框架,在jsp视图打开前,创建session(在线程)对象,在处理完jsp后,jsp服务器返回数并jsp页面打印到浏览器之前,关闭session.可用过滤器(Filter)或拦截器(Interceptor)实现.