1.QBC:条件查询
HQL是面向对象的查询,查询的是对象和对象中的属性
注意:HQL中的关键字不区分大小写,但是类名和属性名区分大小写
2.查询全部
//条件查询对象
Criteria criteria = session.createCriteria(User.class);
//得到集合
List<User> list = criteria.list();
3.查询单个
4.条件查询(重点)
1)Restrictions该类中提供了大量的条件判断的方法
5.分页 设置max最大显示条数和setFierst每页显示条数
6.排序
7.离线查询
//在没有和数据库连接之前先设置查询条件,创建查询对象
DetachedCriteria forClass = DetachedCriteria.forClass(User.class);
//设置查询条件
DetachedCriteria add = forClass.add(Restrictions.like("id", 2));
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
//拿到真真的criteria对象
Criteria criteria = forClass.getExecutableCriteria(session);
Object uniqueResult = criteria.uniqueResult();
System.out.println(uniqueResult);
2.二级缓存:整个应用程序共享一个会话工厂,共享一个二级缓存
1)内置缓存:使用一个Map,用于存放配置信息,预定义SQL语句等,提供给Hibernate框架自己使用,对外只读的。不能操作
2)外置缓存:使用另一个Map,用于存放用户自定义数据。默认不开启。外置缓存hibernate只提供规范(接口),需要第三方实现类。外置缓存有成为二级缓存3.Ehcache
1)导入jar包,
2)开启二级缓存,
<!--开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
3)确定二级缓存的供应商,
<!--确定二级缓存供应商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
4)确定要缓存的对象(一般是只读)
<!--设置要缓存的对象
class:配置要缓存的对象
usage:缓存中的数据是否只读
-->
<class-cache usage="read-only" class="com.qf.entity.User"/>
<class-cache usage="read-only" class="com.qf.entity.Address"/>
5)在缓存集合时候把集合中装的对象也要缓存起来
<!-- 缓存一个集合把集合中对象也给缓存了 -->
<collection-cache usage="read-only" collection="com.qf.entity.User.addresses"/>
6)ehcache配置文件中的属性
1)maxElementsInMemory(正整数): 在内存中缓存的最大对象数量 2)maxElementsOnDisk(正整数): 在磁盘上缓存的最大对象数量,默认值为0,表示不限制。 3)eternal: 设定缓存对象保存的永久属性,默认为 false 。当为 true 时 timeToIdleSeconds、timeToLiveSeconds 失效。 4)timeToIdleSeconds(单位:秒): 对象空闲时间,指对象在多长时间没有被访问就会失效。只对eternal为false的有效。默认值0,表示一直可以访问。 5)timeToLiveSeconds(单位:秒): 对象存活时间,指对象从创建到失效所需要的时间。只对eternal为false的有效。默认值0,表示一直可以访问。 6)overflowToDisk: 如果内存中数据超过内存限制,是否要缓存到磁盘上。 7)diskPersistent: 是否在磁盘上持久化。指重启jvm后,数据是否有效。默认为false。 8)diskSpoolBufferSizeMB(单位:MB): DiskStore使用的磁盘大小,默认值30MB。每个cache使用各自的DiskStore。 9)memoryStoreEvictionPolicy: 如果内存中数据超过内存限制,向磁盘缓存时的策略。默认值LRU,可选FIFO、LFU。 |
适合放入缓存中数据:
a)经常被查询的
b)很少被修改的
不适合放入缓存中数据(安全>效率)
a)很重要的数据,不允许出现并发问题(安全)
3.查询缓存
针对HQL的查询
a)session
开启查询缓存,二级缓存,二级缓存供应商,打开开关
和下面一样的配置,只是不需要确定缓存对象,2个不同的session也可以缓存共享
b)sessionFactory
开启查询缓存,二级缓存,二级缓存供应商,确定缓存对象,打开开关
<!-- 开启查询缓存-->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- 3.设置要缓存的对象 -->
<!--
class:配置要缓存的对象,一般都是read-only
usage:缓存中的数据是否只读
-->
<!-- <class-cache usage="read-write" class="com.qf.entity.User"/>
<class-cache usage="read-only" class="com.qf.entity.Address"/> -->
Query query = session.createQuery("from User u where u.id=:id");
//打开开关
query.setCacheable(true);
query.setInteger("id", 2);
面试题:请你解释以下的作用:
save():把编写好的sql语句放入缓存区中,
flush():把缓存区中的数据刷到数据库中
commit:第一把事务提交
隐式调用flush()
关闭session()
close():关闭session,清空session缓存
clear();清空session缓存
Hibernate中有几种查询方式:
1)主键查询
a)get
b)load
2)HQL查询(用的多)
3)QBC查询
4)原生态sql查询
4.那个查询性能最高
一般来说最原始的jdbc的性能最高,hibernate框架可以帮我们提高开发效率,但是hibernate需要翻译语言,他的查询效率是比不上jdbc的
if (i % 100 == 0) {
session.flush();//刷新进入数据库
session.clear();//清空缓存区
}
prst.addBatch();
if (i % 100 ==0) {
prst.executeBatch();//把缓存区中数据刷入数据库
prst.clearBatch();//清空缓存区
}
5.Hibernate整合c3p0
1.导入jar包
<!--c3p0连接池的信息 -->
<property name="hibernate.c3p0.max_size">30</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.timeout">5000</property>
2.连接池原理
系统初始化时候就创建好一些数据库连接对象到连接池中(内存中),当用户需要访问数据库时候,不创建新的连接对象,而是从连接池中取出空闲的连接对象给用户使用,用户使用完了也不销毁,放回连接池中,给下一个用户使用.连接的创建和销毁都是由连接池来完成.
5.事务级别
数据库中的隔离级别:事务和事务之间的干扰的强度
1,2,4,8:mysql4,8最高
隔离级别不同会产生哪些问题:(发生在2个事务同时操作)
脏读:一个事务读到了另一个事务未提交的数据
不可重复读:一个事务在查询期间,另一个事务在修改,多次查询都得到不同的结果
幻读:T1事务在修改全部数据某个字段为一样的期间,T2事务新增了一行数据,T1事务看到了不一样的数据,就好像幻象一样
修改默认的隔离级别:
mysql,jdbc如何修改
,Hibernate修改
<!--设置数据库的隔离级别-->
<propertyname="hibernate.connection.isolation">4</property>
6.锁(解决并发问题,多个线程访问同一个资源)
悲观锁和乐观锁
悲观锁:修改数据时候总是认为别人也会修改,
原理:for update(数据库的锁机制)
缺点:开销大,对大并发量的的访问不友好
优点:避免了冲突的发生
乐观锁实现的原理:版本号实现
乐观锁:在修改数据时候总会认为别人不会修改
在提交的时候判断版本号是否一致:
如果一致就提交,并且版本号自增;
如果不一致,就不让提交,说明其它事务修改过了
优点:避免了长事务中数据库的加锁解锁开销,大并发量下提高了系统整体性能
缺点:乐观锁只有在提交事务时才能发现业务事务失败,如果系统的冲突非常多,而且一旦失败就要重写提交而造成较大代价,乐观锁也会造成很大问题
*乐观锁是如何保证检查版本,提交和修改版本是同一个原子操作呢?
也就是如何保证在检查版本的期间,没有其他事务对其进行操作?
解决方案: 将比较,更新操作写入到同一条SQL语句中可以解决该问题
共享锁:多个事务对同一数据可以共享一把锁,都能访问到数据,但是只能读不能写
排它锁:称为写锁,一个事务获取了一行的排它锁,其它事务就不能再获取这行的任意锁,获取排它锁的事务可以进行修改和读取
MySQL常用存储引擎的锁机制
MyISAM和MEMORY采用表级锁(table-level locking)
BDB采用页面锁(page-level locking)或表级锁,默认为页面锁
InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁(基于索引)
死锁在操作系统中指的是两个或两个以上的进程在执行的过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或者系统产生了死锁,这些永远在互相等待的进程称为死锁进程。