SessionFactory
1.SessionFactory 中存放着配置文件和所有的映射文件。一个数据库,只能有一个SessionFactory
2.SessionFactory是一个重量级别的类,存放着大量的数据(所有的配置文件和映射文件)
3.一个数据库只能有一个SessionFactory,一个配置文件只能有SessionFactoy
4.只要创建了SessionFactoy,所有的表就创建完毕了
5.SessionFactory中存放的数据是共享数据,但是这个类本身是线程安全的
6.SessionFactory是一个接口,SessionFactory实现类SessionFactoyImpl
映射文件的类型需要注意的是:需要小写
java类型比hibernate类型的效率高,注意 映射文件中的类型首字母大部分都是小写,例如 字符串的java类型需要大写,但是在映射文件中
田用
常见错误
org.hibernate.TransientObjectException:
object references an unsaved transient instance - save the transient instance before flushing: com.zdc.pojo.Student
这就是没有配置级联造成的
只有配置cascade 属性的时候,Hibernate 才会做隐式操作
如果没有cascade属性的时候,隐式对象将会出于临时状态,在两个对象关联的时候,进行保存,HIbernate不允许有临时状态
显式保存:仅仅要session.save 保存一个对象,就是显式保存
隐式保存:间接的保存
Caused by: java.sql.BatchUpdateException:
Cannot delete or update a parent row: a foreign key constraint fails
(`itcast04`.`student`, CONSTRAINT `FK8FFE823B278702AE` FOREIGN KEY (`cid`) REFERENCES `myclass` (`id`))
表示inverse=“true”
级联删除班级 附带删除学生 ,需要修改cascade =“all”
List,ArrayList 去除重复
ArrayList<String> array=new ArrayList<String>();
array.add("zuo");
array.add("zuo");
HashSet<String> strSet=new HashSet<String>(array);
System.out.println(strSet.size());
Session的产生
1.sessionFactory.openSession
每次都会新创建一个session,只要新创建一个session,HIbernate都会打开应用程序和数据库的连接,所以这种方式效率比较低
2.sessionFactory.getCurrentSession`
a.如果当前线程中没有session,先openSession,然后把session存放到当前线程中,
b.从前当前线程中得到session
c.crud操作必须有事物环境
d.不用收到去手动close 关掉session
e.但是需要手动配置HIbernate.cfg.xml添加如下属性
<property name="current_session_context_class">thread</property>
缓存
一级缓存
知识回顾
一级缓存又叫session 缓存,只要打开session,一级缓存就存在了,当session 关闭的时候一级缓存就不存在了。
session 中存放的数据是私有的,不能是共享的, 可以通过新建session和从当前线程中获取session 保存数据的安全性
session.get(),save() 方法得到的对象是一个持久化对象,通过该方法可以把该对象存放到一级缓存当中。
缓存里面有值并不一定数据库中有值。
事物提交之后,session将会关闭
save 方法可以吧一个对象变成持久化对象,也可以把一个对象放入到一级缓存当中
evict清空缓存
session.update()方法能把对象转换成持久化话对象,并且放入到一级缓存当中
session.flush()方法
a.HIbernate 内部回去检查sesion 缓存中的所有对象
b.如果该对象是持久化对象,并且与数据库中的不一样,则会自动放出update 语句,如果该对象的属性没有变化,就不会发出update
c.检查持久化对象是否有关联的对象,如果有关联的对象设置级联操作,并且关联对象发生了变化,也会发出update的语句
Session大批量插入操作
Session sesison=sessionFactory.getCurrentSession();
Transaction transaction = sesison.beginTransaction();
for(int i=0;i<10000;i++)
{
if(i%5==0)
{
sesison.flush();
sesison.clear();
}
Clazz clazz=new Clazz();
clazz.setName("java"+1+"班");
sesison.save(clazz);
}
transaction.commit();
二级缓存:
主要是针对一级缓存
二级缓存是一个共享缓存,存放的数据是共享数据
特性:
修改不能特别频繁
数据可以公开
二级缓存在SessionFactoy中,二级缓存的生命周期和SessionFactoy是一样的
二级缓存配置 :
1.在HIbernate的配置文件中HIbernate.cfg.xml
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
开启二级缓存
<property name="cache.use_second_level_cache">true</property>
2.在对应的实体类的映射文件中添加cache
<cache usage="read-write" />
session.get() 和session.load() 把一个对象变成持久化对象
把该对象保存到session的一级缓存当中
把该对象缓存到二级缓存当中
session.clear(); 清空的一级缓存和二级缓存
session.update();把对象放入到了一级缓存和二级缓存当中
session.save() 该方法只把对象放入到了一级缓存当中,没有放入到二级缓存当中
二级缓存存储到磁盘当中,需要在classpath的文件下添加一个ehcache.xml文件
懒加载 默认的情况下懒加载都为true
org.hibernate.LazyInitializationException: could not initialize proxy - no Session 表示懒加载异常,这里指的
类的懒加载:
默认的情况下,类就是执行懒加载
只有使用了load 方法以后才能用懒加载
如过在响应的映射文件中设置<class>的lazy =false ,懒加载才会失效
集合的懒加载
集合的懒加载是在<set>的集合中添加lazy
集合的懒加载是
true 在遍历集合的时候,发出sql语句的
false在得到集合的时候,发出sql 语句
extra 在调用size()方法的时候,
多对一关联懒加载
false
proxy 就相当于true
no-proxy
根据多的一方加载一的一方,数据量比较少,一般没多大 用
抓取策略
fetch 主要是针对集合而进行的,前提条件是一个对象操作其关联对象,
默认的情况下hibernate 是N+1条
标签中的属性 fetch
join 连接 一般情况下,查询的对象有一个,但是关联的对象是多个,eg:要查询 一个班级id=3的所有学生,这里适合join
select 默认的查询方式
session.createQuery(“From User”) 仅仅加载User 的数据 ,如果再进行遍历的时候才能发出sql 语句去加载相关联的对象
subselect 子查询 ,一般是要查询的对象有多个,然后关联的对象也是多个,这样的话,性能比较高
eg: 查询多个班级的多个学生,
如果是关联查询的时候,会表现出较高的效率