Hibernate中查询实体对象的几种方法:get()、load()、createQuery()、CreateCriteria
使用HQL语句查询不再赘述,下面贴一下HQL语句进行分页查询的代码
HQL语句进行分页查询:
@SuppressWarnings("rawtypes")
@Test
public void testHQL() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
List list = session.createQuery//
("FROM com.test.User ")//
.setFirstResult(0)//
.setMaxResults(10)//
.list();
for (Object obj : list) {
System.out.println(obj);
}
session.beginTransaction().commit();
session.close();
}
使用CreateCriteria()查询:
@SuppressWarnings("rawtypes")
@Test
public void testCriteria() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.ge("id", 1));//过滤条件,ge表示大于,le表示小于
criteria.add(Restrictions.le("id", 5));
criteria.addOrder(Order.desc("id"));//排序条件,id降序输出
List list = criteria.list();
for (Object obj : list){
if(obj.getClass().isArray()){//判断obj类型是否为Array类型并输出,或者直接使用增强for循环遍历输出
System.out.println(Arrays.toString((Object[]) obj ));
} else {
System.out.println(obj);
}
}
session.beginTransaction().commit();
session.close();
}
懒加载:不会在执行获取操作时马上生成SQL,而是在第一次使用时生成SQL
类级别的懒加载:class ….lazy=true
属性级别的懒加载:ser/list/map/bag … lazy = “true” bag的含义相当于口袋,可重复并且无序
在配置文件中配置lazy=”true\false\extra”
lazy=“extra”–增强的懒加载策略
Load()方法:获取数据,是持久化状态–会生成SQL语句–懒加载,不会马上执行SQL语句,而是在第一次使用非id或class属性时执行SQL–
如果对象不存在就报错–load返回的是一个代理对象,要求类不能是final类,否则不能生成代理对象
让懒加载失效的两种方式:
1.把实体写成final类
2.在hbm文件中,将lazy=”flase”加入到配置文件中
在使用懒加载特性时,要注意LazyIxxxxxx异常(懒加载异常),解决懒加载的简单方法:延迟关掉session(让session在加载后再关闭),或者关掉懒加载233
Hibernate.initialize(department.getEmpliyees());//这个方法立即加载指定的懒加载对象,在懒加载开启状态下立即加载指定对象
二级缓存(The Second Level Cache):在SessionFactory中的缓存
一级缓存:SessionCache,针对于一次操作所做的缓存,一级缓存对于性能的提升不大,因为事务的开启和关闭较频繁
使用SessionFactoryCache:
1)在映射文件hbm.xml中书写(映射关系使用映射文件的方式而非注解)
<class name="User" table="OwnuserTest" >
<cache usage="read-only"/>
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" length="10"></property>
<property name="address" length="10"></property>
</class>
2)在hibernate配置文件cfg.xml中书写(推荐使用,解耦和)*
<!-- 使用SessionFactoryCache,默认是未打开的 -->
<property name="cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<mapping resource="com/test/User.hbm.xml"/>
<!-- 指定要使用二级缓存的实体类 -->
<class-cache usage="read-write" class="com.test.User" />
PS:一级缓存和二级缓存都是在使用OID的方式获取对象时才有效;在使用HQL语句查询时,如果使用iterate()方法就会使用缓存,但该方法会有N+1查询的问题,对性能的提升有限
解决方法:打开查询缓存,并在测试中调用setCacheable()方法
@SuppressWarnings("rawtypes")
@Test
public void testQueryCache() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
List list = session.createQuery("FROM com.test.User WHERE id <10")//
.setCacheable(true)
.list();
for (Object obj : list) {
System.out.println(obj);
}
session.beginTransaction().commit();
session.close();
//开启第二个Session,将使用到二级缓存
Session session1 = sessionFactory.openSession();
session1.beginTransaction();
List list1 = session1.createQuery("FROM com.test.User WHERE id <10")//
.setCacheable(true)
.list();
for (Object obj1 : list1) {
System.out.println(obj1);
}
session1.beginTransaction().commit();
session1.close();
}
并在配置文件cfg.xml中打开查询缓存
<!-- 开启使用查询缓存 -->
<property name="cache.use_query_cache">true</property>
注意查询缓存的查询条件需相同,因为h框架是将HQL放入二级缓存中,改变了HQL语句则要重新在数据库中查询,二级缓存无效
PS:在Session缓存中update和delete方法操作了数据库但未更新数据库,但在二级缓存中使用会让二级缓存中的数据失效,下次使用这些数据时会自动在数据库中重新加载
引用网上的资料–hibernate调优等
优化hibernate:
1、使用一对多的双向关联,尽量从多的一端维护。
2、不要使用一对一,尽量使用多对一。
3、配置对象缓存,不要使用集合缓存。
4、表字段要少,表关联不要怕多,有二级缓存撑腰。
Hibernate的调优方案:
1、制定合理的缓存策略;
2、尽量使用懒加载特性;
3、采用合理的Session管理机制;
4、使用批量抓取,设定合理的批处理参数(batch_size);
5、进行合理的O/R映射设计