一 hibernate constrained属性的作用
constrained(约束) (可选) 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。 这个选项影响save()和delete()在级联执行时的先后顺序以及 决定该关联能否被委托(也在schema export tool中被使用).
增加的时候,如果constainted=true,则会先增加关联表,然后增加本表。删除的时候反之。
二 还是配置fetch与unique
<many-to-one name="person" column="person_id" fetch="join" lazy="false" unique="true"></many-to-one>
fetch共两个选项:一个是Join,查询时会产生一个left outer join的查询;另一个是select,会有两个select。
unique,唯一键约束;是生成DDL语言时起作用的。比如创建一个数据库表。由于在hibernate中我们有这样的配置:
<property name="hibernate.hbm2ddl.auto">update</property>
这样就可以看到我们配置的作用了。
三 hibernate 一级缓存,session级共享
save,update,saveOrUpdate,load,get,list,iterate,lock这些方法都会将对象放入一级缓存中,注意一级缓存不能控制缓存的数量,因此在大批量操作数据的时候可能会导致内存溢出;可以使用evict,clear方法清除缓存的内容。既然是session级共享,那么当session关闭后,再次访问这个对象时,就需对数据库进行操作。这样也就有了下面的知识二级缓存。
四 hibernate 二级缓存
二级缓存,hibernate没有自己的实现;需要第三方的框架,当然也可以自己实现,但
是一般实现二级缓存比较复杂,我们都采用第三的框架来实现。其复杂性,在于什么时候需要
访问数据库,什么时候需要访问缓存。一个简单的二级缓存,就是自己定义一个hashTable将我们的对象存入其中,每当访问数据库时我们首先去hashTable中根据自己定义的key规则查找我们的对象是否存在,存在则直接获取,反之访问数据库。当然即使配置二级缓存,我们也需要考虑是否这个数据库表是否经常变化,其影响如何。一般一些常量表,我们可以为它配置二级缓存,而一些经常或者需要避免脏数据、幻影读的表我们都不能为其配置二级缓存。
下面以OSCache为例,配置二级缓存!
首先加入包OSCache的包oscache-2.1.jar和common-logging-1.1.1.jar包,当然每个人版本可以不一样。
oscache-2.1.jar在下面路径中
hibernate-distribution-3.6.0.Final\lib\optional\oscache
添加两个配置:
第一个是hibernate.cfg.xml
下面贴出我所以的配置:
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">njusc123</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/xivadata</property> <!--告诉hibernate所使用的数据库方言 --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="show_sql">true</property> <property name="hibernate.format_sql">true</property> <!-- hibernate自动创建表 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 二级缓存 --> <property name="cache.use_second_level_cache">true</property> <property name="cache.use_query_cache">true</property> <property name="cache.provider_class">org.hibernate.cache.OSCacheProvider</property> <property name="generate_statistics">true</property> <!-- 或者到类配置文件中加入缓存配置 --><!-- <class-cache usage="read-only" class="com.xiva.hibernate.domain.Person"/> <class-cache usage="read-only" class="com.xiva.hibernate.domain.IdCard"/> --> <mapping resource="com/xiva/hibernate/domain/person.hbm.xml"/> <mapping resource="com/xiva/hibernate/domain/department.hbm.xml"/> <mapping resource="com/xiva/hibernate/domain/idCard.hbm.xml"/> </session-factory> </hibernate-configuration>
Query、Criteria(查询缓存)由于命中率较低,所以Hibernate缺省时关闭;修改cache.use_query_cache为true打开对查询的缓存,并且调用query.setCacheable(true)或criteria.setCacheable(true)。
如何查看配置二级缓存:可以从下面路径找到相关配置,
hibernate-distribution-3.6.0.Final\project\etc\hibernate.properties
在该文件中查找:Second-level Cache
第二:复制该路径下面的oscache.properties文件到classes目录下面
为某一个对象配置二级缓存有两种方式:第一就是在hibernate.cfg.xml中加入
<class-cache usage="read-only" class="com.xiva.hibernate.domain.Person"/>
或者在hbm文件中配置,当然现实我们都是使用jpa来配置的,由于现在还没有学习到Jpa,现在提供hbm文件如何配置cache
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!--表明与数据库关键字有冲突时,可在前面加反引号:` --> <hibernate-mapping package="com.xiva.hibernate.domain"> <class name="Person" table="person"> <!-- 配置cache --> <cache usage="read-only"/> <id name="id" unsaved-value="0"> <generator class="native"/> </id> <property name="name" not-null="true" column="name" /> <property name="password" not-null="true"/> <property name="birthday"></property> <component name="address"> <property name="addressLive" column="address01"></property> <property name="addressHome" column="address02"></property> </component> <many-to-one name="department" column="departmentId" not-null="true"></many-to-one> <!-- lazy="false" class="IdCard" constrained="true" lazy="false" <one-to-one name="IdCard" property-ref="person"></one-to-one>--> </class> </hibernate-mapping>
<cache usage="read-only"/>
这个就是缓存配置。
验证二级缓存命中率:
Statistics st = HibernateUtil.getSessionFactory().getStatistics(); System.out.println("HitCount:" + st.getSecondLevelCacheHitCount()); System.out.println("PutCount:" + st.getSecondLevelCachePutCount()); System.out.println("MissCount:" + st.getSecondLevelCacheMissCount());
这个需要在hibernate.cfg.xml文件中配置<property name="generate_statistics">true</property>
五 分布式缓存与中央缓存
使用缓存的条件
1.读取大于修改。
2.数据量不能超过内存容量。
3.对数据要有独享的控制。
4.可以容忍出现无效数据。
#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) #cache.cluster.multicast.ip=231.12.21.132
从上面的配置中可以看出OSCache是支持分布式缓存的。为每一台机器配置好需要同步缓存的ip地址,以及端口号;即当某一台机器数据更新后,则会通知其他机器同步OSCache缓存。当然这个对于更新操作多的数据库表而言,开销是很大的。
关于中央缓存,可以采用memcached来实现。
持续更新中...