Hibernate笔记
基础部分:
注:与数据库建立映射关系的类必须要有有参和无参的构造方法
• hibernate的优缺点:
• 优点:
• 代码比较简单
• 数据缓存:一级缓存 二级缓存 查询缓存
• 移植性比较好
• 缺点:
• Sql语句是hibernate内部自动生成的,不可控。
• 如果数据太大,不适合用hibernate。
2、hibernate配置文件的两种加载方式
public class PersonTest extends HibernateUtils {
@Test
public void testSavePerson(){
// Configuration configuration = new Configuration();
//加载方式一(必须放在src下面并且文件名必须为hibernate.cfg.xml)
// configuration.configure();
//加载方式二(可以指定配置文件的路径和名字)
// configuration.configure("");
// SessionFactory sessionFactory = configuration.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
Person person = new Person();
person.setPname("zt");
person.setPsex("女");
session.save(person);
transaction.commit();
session.close();
}
}
3、SessionFactory sessionFactory = configuration.buildSessionFactory();
sessionFactory是存放数据库的连接信息,映射文件信息,持久化类的信息。
sessionFactory是有单列模式产生的。
一班情况下hibernate应该有一个数据库连接
该类本身是线程安全的。
4、hibernate与java类型
在hibernate的映射文件中的type属性支持两种类型。
Java类型:java.lang.*
Hibernate类型:string,integer,short …..
说明:java类型效率更高。
4、将一个普通java工程变成一个hibernate工程(才可以通过数据库反向编程)
5、主键生成器
increment :
identity :主键不会自动设置为自增,需要手动设置。
uuid :映射类只能是字符串,而且长度要够长。
6、对象的状态
1、Session.clear:是把session中的所有对象清空。
2、Session.evict:把某一个对象从session中清空。(如果想继续执行就必须把状态转为持久化状态)
3、如果一个对象是临时状态的对象,则session不会管。
4、如果一个对象是持久化对象,那么先把该对象与快照相对比,如果一样就什么都不做,如果不一样就发出update语句。
5、如果一个对象是持久化对象,如果没有id就会发出save语句。
7、一对多的单项关联
set元素对应类中的set集合
通过set元素使classes表与student表建立关联
key是通过外键的形式让两张表建立关联
one-to-many是通过类的形式让两个类建立关联
cascade 级联(不管inverse是true还是false都可以删除) :对象与对象之间的关系
save-update
1、当 保存班级的时候,对学生进行怎么样的操作
如果学生对象在数据库中没有对应的值,这个时候会执行save操作
如果学生对象在数据库中有对应的值,这个时候会执行update操作
delete:删除某一个时连通关联的野一起删除
All:上面两个都执行
inverse 维护关系 :对象与外键之间的关系
true 不维护关系
false 维护关系
default false
8、hibernate的流程
Configuraction
加载了配置文件
SessionFactory
配置文件的信息、映射文件的信息、持久化类的信息
Session
1、crud的操作都是由session完成的
2、事务是由session开启的
3、两个不同的session只能用各自的事务
4、session决定了对象的状态
5、创建完一个session,相当于打开了一个数据库的链接
Transaction
1、事务默认不是自动提交的
2、必须由session开启
3、必须和当前的session绑定(两个session不可能共用一个事务)
9、hibernate的原理:
根据客户端的代码,参照映射文件,生成sql语句,利用jdbc技术进行数据库的操作
10、一对多双向操作
1、配置文件:
2、如果让一的一方维护关系,取决于的因素有
1、在一的一方的映射文件中,set元素的inverse属性为default/false
2、在客户端的代码中,通过一的一方建立关系
3、session.save/update方法是用来操作表的,和操作关系没有关系
3、怎么样采用级联的方法通过保存一个对象从而保存关联对象
1、如果session.save操作的对象是A,这个时候应该看A.hbm.xml,看set元素中cascade是否设置有级联保存
2、在客户端通过A建立关联
3、在客户端执行session.save(A)
4、一对多的情况,多的一方维护关系效率比较高
1、在多的一方many-to-one中没有inverse属性
2、在客户端通过多的一方建立关联
14、多对多表的操作
关系操作:
解除关系:在第三张表中删除一条数据
建立关系:在第三张表中添加一条数据
修改关系:先删除后添加
15、性能
懒加载:
类的懒加载:
• 只针对一般属性有效。
• 在得到一般属性时发出sql语句。
• 利用session.load可以产生代理对象。
• 默认情况下就是懒加载。
集合的懒加载:
• 在遍历的时候才会发出sql语句。
• lazy="false":为立即加载
• lazy="true":为懒加载
• 默认为true:延迟加载
•
单端关联的懒加载(多对一):
抓取策略:(如果有子查询,优先选择子查询)
• 研究的主要是set集合如何提取数据
• <set name="students" cascade="save-update" lazy="true" fetch="subselect">
• fetch="subselect":子查询
如果把需求分析翻译成sql语句,存在子查询,这时用子查询效率高。
• fetch="select":默认
是先查询一的一方,再查询多的一方。(发出n+1条sql语句)
• fetch="join":左外链接
如果把需求分析翻译成sql语句,存在子查询,则该策略不起作用。
缓存策略:
Hql语句:
16、session的产生方式
1.Session.openSession:每次都会打开一个新的session,因为每次都会new(见源码)
2.Session.getCurrentSession:到线程里拿session的时候会进行判断,如果已存在就不创建,没有才创建。(见源码)
用法:
必须在配置文件中配置 property:current_session_context_class value:thread
必须在事物的坏境下运行
提交事物的时候会自动关闭session,所以就不用session.clase(session和事物是绑定在一起的)
17、session的缓存:一级缓存
<property name="current_session_context_class">thread</property>
一级缓存的生命周期(session的生命周期)
获得session开启,关闭session结束。
数据库的数据是怎样放到缓存中的
Session.save/get/load/update方法都可以把数据放到缓存中。
缓存中的数据是怎样放到数据库中的
session.Flush() 刷新到数据库的。
客户端怎样从缓存中取数据
利用session.get/load(懒加载)方法都可以把数据从一级缓存中取出。
怎样把缓存中的所有数据清空
Session.clear();
18、一级缓存存放的数据都是私有数据
把session保存到Threadlocal中,不同线程是不能访问的,所以保证了数据的安全性。
清空session中的对象:session.evict(对象名);
19、数据的批处理
session.refresh(student):只会发出sql语句,只刷新不清空。
@Test
public void testSaveBatch(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
for(int i=8;i<1000000;i++){
Student student = new Student();
student.setSname("a"+i);
student.setDescription("b"+i);
session.save(student);
//每50条数据刷新一下内存,不然或导致内存溢出,并清除缓存中的所有数据。
if(i%50==0){
session.refresh(student);
session.clear();
}
}
transaction.commit();
}
20、二级缓存:存放公有数据
二级缓存的实现是依赖第三方插件
必须开启二级缓存
<!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<!-- 二级缓存的提供商 -->
<property name="">
org.hibernate.cache.EhCacheProvider
</property>
1.指定某个对象开启二级缓存
<class-cache usage="read-only" class="com.domain.Classes"/>
2.在映射文件中(在id上面设置)
<cache usage="read-write"/>
21、查询缓存(默认关闭)
开启方法:property:cache.use_query_cache value:true
必须在二级缓存之上
只能在查询语句中使用
在查询类还必须设置:query.setCacheable(true);
两次的查询语句必须一样才会有查询缓存
21、二级缓存大数据解决方法
在src下面放这个配置文件
List<Classes> classes = session.createQuery("from Classes").setCacheable(true).list();
当执行上面语句时,就会到配置文件中区找相对应的name,如果找到了就用找到的那个配置,如果没有找到就用
默认的配置。
22、hql查询
如果页面上要显示的数据和数据库中的数据相差太远,就用select的构造器进行查询时比较好的方法。
反之则用迫切连接比较好。
如果采用迫切连接,from后面跟的那个对象就是结构主体。
如果是多张表查询,就找中间表。
23、工厂模式
24、集合中去除重复的方法
1.先将一个List集合变成一个set集合。
2.再将这个set集合变回List集合。
List<Classes> cList = session.createQuery(hql).list();
Set<Classes> cSet = new HashSet<Classes>(cList);
cList = new ArrayList<Classes>(cSet);
25、把对象放到栈顶的两种方法
ActionContext.getContext().getValueStack().push(user);
ActionContext.getContext().getValueStack().getRoot().add(0, user);
26、把对象放到栈底
ActionContext.getContext().getValueStack().getRoot().add(user);
27、取出栈中的第一个元素
ActionContext.getContext().getValueStack().peek();
ActionContext.getContext().getValueStack().getRoot().get(0);
28、删除栈中的第一个元素
ActionContext.getContext().getValueStack().pop();
Hibernate总结: 待更新!!!!