懒加载 _session.load懒加载_一对一懒加载_one-to-many(元素)懒加载_many-to-one(元素)懒加载_many-to-many(元素)懒加载:
缓存_一级缓存,Session级共享_二级缓存_配置_ 查看缓存信息_清除二级缓存_分布式二级缓存_分布式缓存和中央缓存。
批量更新
asm和cglib两个包实现;Domian是非final的
1.session.load懒加载
一般用在关联数据时。
session = HibernateUtil.getSession();
idCard = (IdCard) session.load(IdCard.class, id);
employee.setDepartment(idCard);
2.一对一懒加载
懒加载只对从对象出现,主对象使用时,不会出现懒加载
必须同事满足下面三个条件时才能实现懒加载
(主表不能有constrained=true,所以主表没有懒加载)
lazy!=false(默认lazy="proxy",使用代理) 2)constrained=true 3)fetch=select (默认)
3.one-to-many(元素)懒加载:
1.lazy!=false 2.fetch=select
4.many-to-one(元素)懒加载:
1.lazy!=false 2.fetch=select
5.many-to-many(元素)懒加载:
1.lazy!=false 2.fetch=select
6.能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,
访问这些懒加载对象(代理对象)的属性(getId和getClass除外)
Hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象:
如:
public Employee query(int empId, boolean includeDepart) { Session session = null; Employee employee = null; try { session = HibernateUtil.getSession(); employee = (Employee) session.get(Employee.class, empId); /********************初始化代理对象********************************/ if (includeDepart) { Hibernate.initialize(employee.getDepartment()); } } finally { if (session != null) { session.close(); } } return employee; }
当相关联的session关闭后,再访问懒加载的对象将出现异常
缓存
缓存的作用主要用来提高性能,可以简单的理解成一个Map;
使用缓存涉及到三个操作:把数据放入缓存、从缓存中获取数据、删除缓存中的无效数据。
一级缓存,Session级共享
save,update,saveOrUpdate,load,get,list,iterate,lock,这些方法都会将对象放在一级缓存中,
※一级缓存不能控制缓存的数量,所以要注意大批量操作数据时可能造成内存溢出;
可以用evict,clear方法清楚缓存中的内容
session.evict(user); session.clear();
二级缓存_配置
1、配置 hibernate.cfg.xml
<!-- 设置使用缓存,默认就是启用的 --> <property name="cache.use_second_level_cache">true</property> <!-- 使用那种缓存,以及使用的包 --> <property name="cache.provider_class">org.hibernate.cache.OSCacheProvider</property>
<!-- 配置缓存的类,也可以在类的配置文件中配置(根据DTD规范加载mapping后面) --> <class-cache usage="read-only" class="com.dwt1220.Employee" />
<class-cache class="com.dwt.Employee" usage="read-write"/>中
usage 值
read-only 这个类只读取,不修改
read-write 读取和修改
nonstrict-read-write 不严谨的读取和修改,如:可能会吞帖。
transactional 使用事物回滚功能,(一般没有这功能)
2.、添加缓存框架使用的配置文件(放入Classpath中)
这里使用的是OS缓存。添加
oscache.properties 文件
缓存文件中有默认属性,需要配置的是cache.capacity=1000 缓存的对象数
3、类的映射文件中配置类缓存
在ID标签前添加<cache usage="read-write"/>
<class name="Employee"> <cache usage="read-write" /> <id name="id"> <generator class="hilo" /> </id> <property name="name" /> </class>
查看缓存信息
在hibernate.cfg.xml中添加 hibernate.generate_statistics
<property name="hibernate.generate_statistics">true</property>
Test.java中
Statistics statistics= HibernateUtil.getSessionFactory().getStatistics(); System.out.println("Hit:"+statistics.getSecondLevelCacheHitCount()); System.out.println("Put:"+statistics.getSecondLevelCachePutCount()); System.out.println("Miss:"+statistics.getSecondLevelCacheMissCount());
清除二级缓存
evict()方法
HibernateUtil.getSessionFactory().evict(user.class); HibernateUtil.getSessionFactory().evict(user.class,id);
分布式缓存
配置(oscache.properties)
#cache.cluster.properties=UDP(mcast_addr=231.12.21.132;mcast_port=45566;ip_ttl=32;mcast_send_buf_size=150000;mcast_recv_buf_size=80000):PING(timeout=2000;num_initial_members=3):MERGE2(min_interval=5000;max_interval=10000):FD_SOCK:VERIFY_SUSPECT(timeout=1500):pbcast.NAKACK(gc_lag=50;retransmit_timeout=300,600,1200,2400,4800):pbcast.STABLE(desired_avg_gossip=20000):UNICAST(timeout=5000):FRAG(frag_size=8096;down_thread=false;up_thread=false):pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=false;print_local_addr=true)
中央缓存。
批量更新
大量操作数据时可能造成内存溢出,解决办法如下:
1.清除session中的数据
for(int i=0;i<100000;i++)session.save(obj);
for(int i=0;i<100000;i++){
session.save(obj);
if(i% 50 == 0){session.flush(); session.clear();}
}
2.用StatelessSession接口:它不和一级缓存、二级缓存交互,也不触发任何事件、监听器、拦截器,通过该接口的操作会立刻发送给数据库,与JDBC的功能一样。
StatelessSession s = sessionFactory.openStatelessSession();该接口的方法与Session类似。
3.Query.executeUpdate()执行批量更新,会清除相关联的类二级缓存(sessionFactory.evict(class)),也可能会造成级联,和乐观锁定出现问题