??xml version="1.0" encoding="utf-8" standalone="yes"?>
二~存也称q程U的~存或SessionFactoryU的~存Q而二U缓存可以被所有的session(hibernate中的)׃n二~存的生命周期和SessionFactory的生命周期一_SessionFactory可以理二~存
二~存的配|和使用Q?/p>
1.echcache.xml文g拯到src? 二~存hibernate默认是开启的Q手动开?/p>
2.开启二U缓存,修改hibernate.cfg.xml文g,
<property name=”hibernate.cache.user_second_level_cache”>true</property>
3.指定~存产品提供?/p>
<property name=”hibernate.cache.provider_calss”>org.hibernate.cache.EhCacheProvider</property>
4.指定那些实体cM用二U缓存(两种ҎQ推荐用第二种Q?/p>
W一U:?.hbm.xml中,?lt;id>之前加入
<cache usage=”read-only” />, 使用二~存
W二U:在hibernate.cfg.xml配置文g??lt;mapping resource=”com/Studnet.hbm.xml” />后面加上Q?/p>
<class-cache class=” com.Studnet” usage=”read-only” />
二~存是缓存实体对象的
了解一U缓存和二~存的交?/p>
试二~存Q?/strong>
一Q开启两?/strong>session中发Z?/strong>load查询Q?/strong>get?/strong>load一P同样不会查询数据库),
Student sutdent = (Student)session.load(Student.class,1);
sessioin.close();
………..
开启两个session中发Zơload查询Q第一ơload的时候不会去查询数据库,因ؓ他是LAZY的,当用的时候才L询数据库Q?nbsp; 二.开启两?/strong>sessionQ分别调?/strong>loadQ再使用sessionFactory清楚二~存 Student sutdent = (Student)session.load(Student.class,1); sessioin.close(); ……….. SessionFactory factory = HibernateUtil.getSessionFactory(); //factory.evict(Student.class); //清除所有Student对象 Factory.evict(Student.class,1); //清除指定id=1 的对?/p>
开启两个session中发Zơload查询Q第一ơload的时候不会去查询数据库,因ؓ他是LAZY的,当用的时候才L询数据库Q?nbsp; 三.一U缓存和二~存的交?/strong> session.setCacheMode(CacheMode.GET); Student sutdent = (Student)session.load(Student.class,1); sessioin.close(); ……….. SessionFactory factory = HibernateUtil.getSessionFactory(); //factory.evict(Student.class); //清除所有Student对象 Factory.evict(Student.class,1); //清除指定id=1 的对?/p>
开启两个session中发Zơload查询Q第一ơload的时候不会去查询数据库,因ؓ他是LAZY的,当用的时候才L询数据库Q?nbsp; session.setCacheMode(CacheMode.PUT); Student sutdent = (Student)session.load(Student.class,1); sessioin.close(); ……….. SessionFactory factory = HibernateUtil.getSessionFactory(); //factory.evict(Student.class); //清除所有Student对象 Factory.evict(Student.class,1); //清除指定id=1 的对?/p>
开启两个session中发Zơload查询Q第一ơload的时候不会去查询数据库,因ؓ他是LAZY的,当用的时候才L询数据库Q?nbsp; 一U缓存很短和session的生命周期一_一U缓存也叫sessionU的~存或事务缓?/p>
哪些Ҏ支持一U缓存: *get() *load() *iterate() 如何理一U缓存: * session.clear() session.evict() 如何避免一ơ性大量的实体数据入库D内存溢出 *先flushQ再clear 如果数据量特别大Q考虑采用jdbc实现Q如果jdbc也不能满求,可以考虑采用数据库本w的特定导入工具 一Q?/strong>Load试: 在同一?/strong>session中发Z?/strong>load查询 Load试: 开启两?/strong>session中发Z?/strong>load查询 Student sutdent = (Student)session.load(Student.class,1); sessioin.close(); ……….. 二.Get试: 在同一?/strong>session中发Z?/strong>get查询 三.iterate试: 在同一?/strong>session中发Z?/strong>iterator查询 Student student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next(); System.out.println(student.getName()); student = (Student)session.createQuery(“from Student s where s.id=1”).iterate().next(); System.out.println(student.getName()); 四.Iterate查询属性测?/strong>: 同一?/strong>session中发Zơ查询属?/strong> String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next(); System.out.println(name); String name = (String)session.createQuery(“select s.name from Student s where s.id=1”).iterate().next(); System.out.println(name); Student sutdent = (Student)session.load(Student.class,id); save的时候,他会在缓存里放一?不会发出sqlQ因为save是用缓存的 六.同一?/strong>session中先调用load查询Q然后执?/strong>sessio.clear()?/strong>session.evict()Q再调用load查询 Student sutdent = (Student)session.load(Student.class,1); Student sutdent = (Student)session.load(Student.class,1); 上面的语句都会发出sql 因ؓ一U缓存中的实体被清除?/p>
七.向数据库中批量加?/strong>1000条数?/strong> for(int i=0;i<1000;i++){ //?0条数据就强制session数据持久化Q同时清除缓存,避免大量数据造成内存溢出 } } hibernate查询~存(hibernate默认是关闭的) 查询~存是针Ҏ通属性结果集的缓?/p>
对实体对象的l果集只~存id 查询~存的生命周期,当前兌的表发生修改Q那么查询缓存生命周期结?/p>
查询~存的配|和使用Q?/p>
1. 启用查询~存Q在hibernate.cfg.xml中加入: <property name=”hibernate.cache.use_query_cache”>true</property> 试查询~存Q?/strong> 一Q?nbsp; Query query = session.createQuery(“select s.name from Student s”); //启用查询~存 query.setCacheable(true); List names = query.list(); for(Iterator iter = names.terator();iter.hasNext();){ } System.out.println(“------------------------------------------”); query = session.createQuery(“select s.name from Student s”); //启用查询~存 query.setCacheable(true); names = query.list(); for(Iterator iter = names.terator();iter.hasNext();){ } W二ơ没有去查询数据库,因ؓ启用了查询缓?/p>
二. Query query = session.createQuery(“select s.name from Student s”); //启用查询~存 query.setCacheable(true); List names = query.list(); for(Iterator iter = names.terator();iter.hasNext();){ } session.close(); System.out.println(“------------------------------------------”); ……… Query query = session.createQuery(“select s.name from Student s”); //启用查询~存 query.setCacheable(true); List names = query.list(); for(Iterator iter = names.terator();iter.hasNext();){ } W二ơ没有去查询数据库,因ؓ查询~存生命周期与session生命周期无关 三. Query query = session.createQuery(“select s.name from Student s”); //启用查询~存 query.setCacheable(true); for(Iterator iter =query.iterate();iter.hasNext();){ } session.close(); System.out.println(“------------------------------------------”); ……… Query query = session.createQuery(“select s.name from Student s”); //启用查询~存 query.setCacheable(true); for(Iterator iter = query.iterate();iter.hasNext();){ } W二L询数据库Q因为查询缓存只对query.list()起作用,对query.iterate()不v作用,也就是说query.iterate()不用查询缓?/p>
四. Query query = session.createQuery(“ from Student s”); //query.setCacheable(true); List students = query.list(); for(Iterator iter = students.iterate();iter.hasNext();){ } session.close(); System.out.println(“------------------------------------------”); ……… Query query = session.createQuery(“ from Student s”); //query.setCacheable(true); List students = query.list(); for(Iterator iter = students.iterate();iter.hasNext();){ } W二L询数据库Q因为list默认每次都会发出查询sql 五. Query query = session.createQuery(“ from Student s”); query.setCacheable(true); List students = query.list(); for(Iterator iter = students.iterate();iter.hasNext();){ } session.close(); System.out.println(“------------------------------------------”); ……… Query query = session.createQuery(“ from Student s”); query.setCacheable(true); List students = query.list(); for(Iterator iter = students.iterate();iter.hasNext();){ } W二L询数据库Ӟ会发出N条sql语句Q因为开启了查询~存Q关闭了二~存Q那么查询缓存会~存实体对象的idQ所以hibernate会根据实体对象的idL询相应的实体Q如果缓存中不存在相应的实体Q那么将发出Ҏ实体id查询的sql语句Q否则不会发出sqlQ用缓存中的数?/p>
六. Query query = session.createQuery(“ from Student s”); query.setCacheable(true); List students = query.list(); for(Iterator iter = students.iterate();iter.hasNext();){ } session.close(); System.out.println(“------------------------------------------”); ……… Query query = session.createQuery(“ from Student s”); query.setCacheable(true); List students = query.list(); for(Iterator iter = students.iterate();iter.hasNext();){ } W二不会发出sqlQ因为开启了二~存和查询缓存,查询~存~存了实体对象的id列表Qhibernate会根据实体对象的id列表CU缓存中取得相应的数?/p>
]]>
]]>
查询数据库每ơ最多返?/strong>50条结果:
<property name=”hibernate.jdbc.fetch_size”>50</property>
30条更新数据库一?/strong>:
<property name= ”hibernatejdbc.batch_size”>30</property>
一Q?/strong>hibernate 抓取{略(Fetch) 单端代理扚w抓取
1.fetch=”select” 兌实体
//fetch 默认是select
<many-to-one name="businessId" column="business_id" insert="true" update="true" fetch="select">
Student student = (Student)session.load(Student.class,1);
System.out.println(student.getName());
System.out.println(student.getClasses().getName()); //多对一中的属性班U,获取班名称
Fetch=”select” ,上面E序会发2条sql语句Q第二条发送一条select语句抓取当前对象兌实体或集?(q里指是班名称)
2.fetch=” join” 兌实体
//fetch 讄?join
<many-to-one name="businessId" column="business_id" insert="true" update="true"
fetch=" join ">
Student student = (Student)session.load(Student.class,1);
System.out.println(student.getName());
System.out.println(student.getClasses().getName()); //多对一中的属性班U,获取班名称
fetch=” join” , 上面E序会发1条sql语句Q?hibernate会通过select使用外链接来加蝲其关联实体或集合Q此时lazy会失?nbsp;
二.hibernate 抓取{略(Fetch) 集合代理扚w抓取
1.
//fetch 默认是select
<set name="students" inverse="true" cascade="all" fetch="select">
</set>
Classes cla = (Classes)session.load(Classes.class,1);
System.out.println(cla.getName());
for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){
}
fetch=”select” ,上面E序用到了就发sql语句,W二从@环中发了N?如果Qfetch=”subselect”,则只是发送一条语句,见下?/p>
2 fetch=”join”
//fetch 讄成join
<set name="students" inverse="true" cascade="all" fetch="join">
</set>
Classes cla = (Classes)session.load(Classes.class,1);
System.out.println(cla.getName());
for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){
}
Fetch=”select” ,上面E序只发了一条sql语句
三.hibernate 抓取{略(Fetch) 集合代理扚w抓取
2.
//fetch讄成subselect
<set name="students" inverse="true" cascade="all" fetch="subselect">
</set>
List classesList = session.createQuery(“select c from Classes c where c.id in(1,2,3)”);
for(Iterator iter=classesList.iterator();iter.hasNext();){
}
}
Fetch=”subselct” ,另外发送一条select语句抓取在前面查询到的所有实体对象的兌集合
四.hibernate 扚w{略batch-size属性,可以扚w加蝲实体c,
参见Classes.hbm.xmlQ同旉合也可以是用,如:
在配|文件hbm.xml 讄中:
<class name="com.Classes " table="tb_classes" batch-size=”3”>
List students = session.createQuery(“select s from Student s where s.id in(:ids)”).setParameterList(“:ids”,new Object[]{1,11,21,31,41,51,61,71,81,91}).list();
for(Iterator iter=students.iterator();iter.hasNext();){
}
当第二个for循环Ӟ每次加蝲 之前讄?数量 实体对象,
举个例子Q?/p>
//查询id=1的那条记录,使用悲观?/p>
User user = (User)session.load(User.class, 1 , 使用了数据库中的 for update 乐观?/strong> 大多数基于数据版本记录机ӞversionQ实玎ͼ一半是在数据库表加入一个version字段Q读取数据时版本号一同读出,之后更新数据时版本号加一Q如果提交数据时版本号小于或{于数据库表中的版本P则认为数据是q期的,否则l予更新?/p>
其实q是锁Q是一U冲H检?nbsp; ?.hm.xml?dU色部分Q?/p>
<class name="com.tao3c.orm.TbBusinessInfo" 其中version是com.tao3c.orm.TbBusinessInfocȝ属性,hiernbate会去l护的,不用自己去该
]]>
举个例子Q?/p>
//查询id=1的那条记录,使用悲观?/p>
User user = (User)session.load(User.class, 1 , 使用了数据库中的 for update 乐观?/strong> 大多数基于数据版本记录机ӞversionQ实玎ͼ一半是在数据库表加入一个version字段Q读取数据时版本号一同读出,之后更新数据时版本号加一Q如果提交数据时版本号小于或{于数据库表中的版本P则认为数据是q期的,否则l予更新?/p>
其实q是锁Q是一U冲H检?nbsp; ?.hm.xml?dU色部分Q?/p>
<class name="com.tao3c.orm.TbBusinessInfo" 其中version是com.tao3c.orm.TbBusinessInfocȝ属性,hiernbate会去l护的,不用自己去该
]]>
User--à Role
user(id,name)
Userc:
private int
Rolec:
private int id;
User.hbm.xml中:
<set name=”roles” table=”t_user_role”>
</set>
q样Qhibernate会自动生中间表t_user_role(userid,roleid) q且是复合主键,userid为t_user的外键,roleid为t_role的外?/p>
二.hibernate多对多的存储
Role r1 = new Role();
r1.setName(“数据录入人员”);
Role r2 = new Role();
r2.setName(“商务ȝ”);
Role r3 = new Role();
r3.setName(“大区l理”);
User u1 = new User();
u1.setName(“10”);
Set u1Roles = new HashSet();
u1Roles.add(r1);
u1Roles.add(r2);
u1.setRoles(u1Roles);
User u2 = new User();
u1.setName(“儿”);
Set u2Roles = new HashSet();
u2Roles.add(r2);
u2Roles.add(r3);
u2.setRoles(u2Roles);
User u3 = new User();
u3.setName(“Cu”);
Set u3Roles = new HashSet();
u3Roles.add(r1);
u3Roles.add(r2);
u3Roles.add(r3);
u3.setRoles(u3Roles);
session.save(r1);
session.save(r2);
session.save(r3);
session.save(u1);
session.save(u2);
session.save(u3);
l束之后Q在W三张表中也有数?/p>
三.hibernate多对多的加蝲
User user = (User)session.load(User.class,1);
System.out.println(user.getName());
for(Iterator iter = user.getRoles().iterator();iter.hasNext();){
}
三.hibernate多对多的 双向映射
User ß--.-àRole
user(id,name)
Userc:
private int
Rolec:
private int id;
User.hbm.xml中:
<set name=”roles” table=”t_user_role”>
</set>
Role.hbm.xml中:
<set name=”roles” table=”t_user_role”>
</set>
注意Q上面中间表名字是一L
q样Qhibernate也会自动产生中间表t_user_role(userid,roleid) q且是复合主键,userid为t_user的外键,roleid为t_role的外?/p>
User--à Role
user(id,name)
Userc:
private int
Rolec:
private int id;
User.hbm.xml中:
<set name=”roles” table=”t_user_role”>
</set>
q样Qhibernate会自动生中间表t_user_role(userid,roleid) q且是复合主键,userid为t_user的外键,roleid为t_role的外?/p>
二.hibernate多对多的存储
Role r1 = new Role();
r1.setName(“数据录入人员”);
Role r2 = new Role();
r2.setName(“商务ȝ”);
Role r3 = new Role();
r3.setName(“大区l理”);
User u1 = new User();
u1.setName(“10”);
Set u1Roles = new HashSet();
u1Roles.add(r1);
u1Roles.add(r2);
u1.setRoles(u1Roles);
User u2 = new User();
u1.setName(“儿”);
Set u2Roles = new HashSet();
u2Roles.add(r2);
u2Roles.add(r3);
u2.setRoles(u2Roles);
User u3 = new User();
u3.setName(“Cu”);
Set u3Roles = new HashSet();
u3Roles.add(r1);
u3Roles.add(r2);
u3Roles.add(r3);
u3.setRoles(u3Roles);
session.save(r1);
session.save(r2);
session.save(r3);
session.save(u1);
session.save(u2);
session.save(u3);
l束之后Q在W三张表中也有数?/p>
三.hibernate多对多的加蝲
User user = (User)session.load(User.class,1);
System.out.println(user.getName());
for(Iterator iter = user.getRoles().iterator();iter.hasNext();){
}
三.hibernate多对多的 双向映射
User ß--.-àRole
user(id,name)
Userc:
private int
Rolec:
private int id;
User.hbm.xml中:
<set name=”roles” table=”t_user_role”>
</set>
Role.hbm.xml中:
<set name=”roles” table=”t_user_role”>
</set>
注意Q上面中间表名字是一L
q样Qhibernate也会自动产生中间表t_user_role(userid,roleid) q且是复合主键,userid为t_user的外键,roleid为t_role的外?/p>
1.两种配置文gQ?/p>
A.hibernate.cfg.xml和B.hibernate.properties
A中可含映文件的配置Q而B中hard codes加映文件?/p>
A.Configuration config=new Configuration().config();
B. Configuration config=new Configuration();
config.addClass(TUser.class);
2.你不必一定用hibernate.cfg.xml或hibernate.propertiesq两文g名,你也不一定非得把配置文g攑֜Classes下, File file=new File("c:\\sample\\myhibernate.xml"); Configuration config=new Configuration().config(file);
3. session.Flush() 强制数据库立卛_步,当用事务Ӟ不必用flush,事务提交自动调用flush在session关闭时也会调用flush
4. HibernateL使用对象cd作ؓ字段cd
5. XDoclet专门建立了hibernate doclet,是在java代码上加上一些java docTagQ后来再让XDoclet分析该java代码Q生成映文?
6.HQL子句本n大小写无养I但是其中出现的类名和属性名必须注意大小写区分?/p>
7.关系Q Constrained : U束Q表明主控表的主键上是否存在一个外键(foreigh keyQ对其进行约束?/p>
property-ref:兌cM用于与主控类相关联的属性名Q默认ؓ兌cȝ主键属性名
单向一对多需在一斚w|,双向一对多需在双方进行配|?/p>
8.lazy=false:被动方的记录由hibernate负责记取Q之后存攑֜LҎ定的Collectioncd属性中
9. java.util.Set或net.sof.hibernate.collecton.Bagcd的Collection
10.重要Qinverse:用于标识双向兌中的被动方一端?/p>
inverse=false的一方(L方)负责l护兌关系.默认|false
11.batch-size:采用延迟加蝲特征Ӟ一ơ读入的数据数昨?/p>
12.一对多通过LҎ斎ͼL方ؓ一ҎQ?/p>
user.getAddresses().add(addr);
session.save(user);//通过L对象U联更新
13.在one-to-many 关系中,many 一方设Z动方Qinverse=falseQ将有助性能的改善。在一方设|关pLQinverse=true,卛_L权交l多方, q样多方可主动从一方获得foreign key,然后一ơinsert卛_完工?/p>
addr.setUser(user);//讄兌的TUser对象
user.getAddresses().add(addr);
session.save(user);//U联更新
14.只有设ؓL方的一Ҏ兛_Q访问)Ҏ的属性,被动Ҏ不关心对方的属性的?/p>
15.one-to-many与many-to-one节点的配|属性不同:
一对多关系多了lazy和inverse两个属性多对多节点属性:
column:中间映射表中Q关联目标表的关联字D?/p>
class:cdQ关联目标类
outer-join:是否使用外联?/p>
注意:access是设|属性值的d方式?/p>
column是设|关联字Dc?/p>
16.多对多,注意两方都要讄inverse和lazy,cascade只能设ؓinsert-update
多对多关pMQ由于关联关pL两张表相互引用,因此在保存关pȝ态时必须对双方同时保存?/p>
group1.getRoles().add(role1); role1.getGroups().add(group1);
session.save(role1); session.save(group1);
17.关于vo和po vol过hibernate定w处理Q就变成了po(该vo的引用将被容器保存,q且在session关闭时flush,因此po如果再传到其它地Ҏ变了Q就危险? vo和po怺转换QBeanUtils.copyProperties(anotherUser,user);
18.对于save操作而言Q如果对象已l与Session相关联(卛_l被加入Session的实体容器中Q,则无需q行具体的操作。因Z后的Session.flushq程中,Hibernate 会对此实体容器中的对象进行遍历,查找出发生变化的实体Q生成ƈ执行相应的update 语句?/p>
19.如果我们采用了gq加载机Ӟ但希望在一些情况下Q实现非延迟加蝲时的功能Q也是_我们希望在Session关闭后,依然允许操作user的addresses 属?Hibernate.initializeҎ可以通过强制加蝲兌对象实现q一功能Q?q也正是我们Z么在~写POJOӞ必须用JDK Collection接口Q如Set,MapQ? 而非特定的JDK Collection实现c(如HashSet、HashMapQ申明Collection属性的 原因?/p>
20.事务Q从sessionFactory获得session,其自动提交属性就已经关闭(AutoCommit=false),此时若执行了jdbc操作Q如果不昑ּ调用session.BeginTransaction(),是不会执行事务操作的?/p>
jdbc transaction:Z同一个session(是同一个connection)的事?
jta transaction:跨sessionQ跨connectionQ事?
对于jta事务Q有三种实现ҎQ?/p>
A。UserTransaction tx=new InitialContext().lookup("...");
tx.commit();
B. 使用hibernate装的方法:(不推?
Transaction tx=session.beginTransaction();
tx.commit();
C. 使用ejb之sessionBean的事务技持方法,你只要在把需要在发布描述W中Q把需要jta事务的方法声明ؓrequire卛_
21.悲观锁,乐观锁: 乐观锁一般通过version来实玎ͼ注意version节点必须出现在id后?/p>
22.Hibernate中,可以通过Criteria.setFirstResult和Criteria.setFetchSizeҎ讑֮分页范围?/p>
Query接口中也提供了与其一致的ҎQhibernate主要在dialectcM实现在这个功能?/p>
23.cache
……
net.sf.ehcache.hibernate.Provider
q需对ecache本nq配|?/p>
之后在映文件中指定各个映射实体的cache{略
....
....
***************************************************** Query.list()跟Query.iterate()的不同:对于query.list()L通过一条sql语句获取所有记?然后其dQ填入pojoq回; 但是query.iterate()Q则是首先通过一条Select SQL 获取所有符合查询条件的记录?idQ再对这个id 集合q行循环操作Q通过单独的Select SQL 取出每个id 所对应的记 录,之后填入POJO中返回?/p>
也就是说Q对于list 操作Q需要一条SQL 完成。而对于iterate 操作Q需要n+1 条SQL。,listҎ不会从Cache中读取数据。iterator却会?/p>
24.ThreadLocal:它会为每个线E维护一个私有的变量I间。实际上Q?其实现原理是在JVM 中维护一个MapQ这个Map的key 是当前的线E对象,而value则是U程通过ThreadLocal.setҎ保存的对象实例。当U程调用ThreadLocal.getҎӞ ThreadLocal会根据当前线E对象的引用Q取出Map中对应的对象q回?/p>
q样QThreadLocal通过以各个线E对象的引用作ؓ区分Q从而将不同U程的变量隔d来?/p>
25.Hibernate官方开发手册标准示?
public class HibernateUtil { private static SessionFactory sessionFactory;
static { try { // Create the SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (HibernateException ex) { throw new RuntimeException( "Configuration problem: " + ex.getMessage(), ex );
} } public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException { Session s = (Session) session.get();
// Open a new Session, if this Thread has none yet if (s == null) { s = sessionFactory.openSession();
session.set(s);
} return s;
} public static void closeSession() throws HibernateException { Session s = (Session) session.get();
session.set(null);
if (s != null) s.close();
} }
26.通过filter实现session的重用:
public class PersistenceFilter implements Filter { protected static ThreadLocal hibernateHolder = new ThreadLocal();
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { hibernateHolder.set(getSession());
try { …… chain.doFilter(request, response);
…… } finally { Session sess = (Session)hibernateHolder.get();
if (sess != null) { hibernateHolder.set(null);
try { sess.close(); } catch (HibernateException ex) { throw new ServletException(ex);
} } } } ……}