zoukankan      html  css  js  c++  java
  • hibernate学习(9)——日志,一对一,二级缓存

    1、Hibernate中的日志

    1  slf4j 核心jar  : slf4j-api-1.6.1.jar 。slf4j是日志框架,将其他优秀的日志第三方进行整合。

    整合导入jar包

           log4j 核心包:log4j-1.2.17.jar

           过渡jar(整合jar):slf4j-log4j12-1.7.5.jar

     导入配置文件

           log4j.properties  ,此配置文件通知log4j 如何输出日志

      配置文件内容:

           1.记录器

           2.输出源

           3.布局

    1 记录器

           例如: log4j.rootLogger=info, stdout,file

           格式:log4j.rootLogger=日志级别, 输出源1,输出源2,。。。。

           log4j 日志级别 : fatal 致命错误 error 错误 warn 警告 info 信息 debug 调试信息 trace 堆栈信息 (由高到底顺序)

    2 输出源:

           例如:log4j.appender.file=org.apache.log4j.FileAppender

           格式:log4j.appender.输出源的名称=输出源的实现类

                  名称:自定义

                  实现类:log4j提供

           输出源属性例如:log4j.appender.file.File=d:mylog.log

           输出源属性格式:log4j.appender.名称.属性=值

                  每一个输出源对应一个实现类,实现类都属性(setter),底层执行setter方法进行赋值

    3 常见的输出源实现类

           org.apache.log4j.FileAppender  输出文件中

                  file ,表示文件输出位置

           org.apache.log4j.ConsoleAppender 输出到控制台

                  Target ,表示使用哪种输出方式,在控制台打印内容,取值:System.out / System.err

    4 布局  -- 确定输出格式

           例如:log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

           格式:log4j.appender.数据源.layout=org.apache.log4j.PatternLayout

           布局属性:log4j.appender. 数据源.layout.ConversionPattern=值

                  12:56:30,123  info

    5 扩展:对指定的目录设置日志级别

           例如:log4j.logger.org.hibernate.transaction=debug

           格式:log4j.logger.包结构=级别

    2、一对一

    1  情况1:主表的主键,与从表的外键(唯一),形成主外键关系

    2  情况2:主表的主键,与从表的主键,形成主外键关系 (从表的主键又是外键)

    情况1实现:

    <hibernate-mapping package="com.alice.hibernate03.vo">
         <class name="Address" table="t_address">
            <id name="id" column="id">
               <generator class="native"></generator>
            </id>
            
            <property name="name" column="name" type="string"></property>
            <!-- 一对一:特殊的多对一,使用外键的方式 -->
            <many-to-one name="company" class="Company" column="cid" update="true"></many-to-one>
         </class>
    </hibernate-mapping>
    
    <hibernate-mapping package="com.alice.hibernate03.vo">
         <class name="Company" table="t_company">
            <id name="id" column="id">
               <generator class="native"></generator>
            </id>
            <property name="name" column="name" type="string"></property>
            <!-- 一对一关系 -->
            <one-to-one name="address" class="Address" property-ref="company"></one-to-one>
         </class>
    </hibernate-mapping>
    

      

    package com.alice.hibernate03.one;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    
    import com.alice.hibernate03.util.HibernateUtil;
    import com.alice.hibernate03.vo.Address;
    import com.alice.hibernate03.vo.Company;
    
    public class OneTest {
        @Test
    	public void test01(){
        	Session session = HibernateUtil.openSession();
        	Transaction tran = session.beginTransaction();
        	
        	Company company = new Company();
        	company.setName("西电");
        	
        	Address address = new Address();
        	address.setName("雁塔区");
            //注意,在一对一使用外键时,外键所在对象才能维护关系,另一方无法维护
        	address.setCompany(company);
        	
        	
        	
        	session.save(company);
        	session.save(address);
        	
        	tran.commit();
        	session.close();
        }
        
        @Test
        public void test02(){
        	Session session = HibernateUtil.openSession();
        	Transaction tran = session.beginTransaction();
        	
        	Company company = (Company) session.get(Company.class, 1);
        	
        	System.out.println(company);
    
        	
        	tran.commit();
        	session.close();
        }
    }
    

      

    情况2实现:

     <class name="Address" table="t_address">
            <id name="id" column="id">
               <!-- foreign: 该主键既是主键又是外键 -->
               <generator class="foreign">
                  <!-- 作为外键时引用哪个属性 -->
                  <param name="property">company</param>
               </generator>
            </id>
            
            <property name="name" column="name" type="string"></property>
           <!-- 配置一对一关系 -->
            <one-to-one name="company" class="Company" constrained="true"></one-to-one>
    

      

     <class name="Company" table="t_company">
            <id name="id" column="id">
               <generator class="native"></generator>
            </id>
            <property name="name" column="name" type="string"></property>
            <!-- 配置一对一
    		one-to-one : 默认使用主键同步策略完成一对一的表关系体现.
    		cascade:
    		fetch:
    		lazy:
    		 -->
            <one-to-one name="address" class="Address"></one-to-one>
         </class>
    

    3、二级缓存

    缓存(Cache): 计算机领域非常通用的概念。它介于应用程序永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写硬盘(永久性数据存储源)的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存

           缓存:程序<--(内存)-->硬盘

    3.1   什么是二级缓存

    1  hibernate 提供缓存机制:一级缓存、二级缓存

           一级缓存:session级别缓存,在一次请求中共享数据。

           二级缓存:sessionFactory级别缓存,整个应用程序共享一个会话工厂,共享一个二级缓存。

    2  SessionFactory的缓存两部分:   内置缓存:使用一个Map,用于存放配置信息,预定义HQL语句等,提供给Hibernate框架自己使用,对外只读的。不能操作。

           外置缓存:使用另一个Map,用于存放用户自定义数据。默认不开启。外置缓存hibernate只提供规范(接口),需要第三方实现类。外置缓存有成为二级缓存。

    3 二级缓存内部结构

    l  二级就是由4部分构成

    1)  类级别缓存

    2) 集合级别缓存

    3) 时间戳缓存

    4)  查询缓存(二级缓存的第2大部分,三级缓存)

    4    并发访问策略

    一般用 访问策略:读写型(read-write)、只读型(read-only)

    5    应用场景

    1 适合放入二级缓存中的数据:

           很少被修改

           不是很重要的数据, 允许出现偶尔的并发问题

    2  不适合放入二级缓存中的数据:

           经常被修改

           财务数据, 绝对不允许出现并发问题

           与其他应用数据共享的数据

    3.2 配置

    1.导入jar包:ehcache-1.5.0.jar/ commons-logging.jar/ backport-util-concurrent.jar

    2.开启二级缓存(我要使用二级缓存)

    在hibernate.cfg.xml 配置二级缓存

    3.确定二级缓存提供商(我要使用哪个二级缓存)

    4.确定需要缓存内容

           1>配置需要缓存的类

           2>配置需要缓存的集合

    在hibernate.cfg.xml 确定 类缓存 和集合缓存配置项

    代码实现:

    <!-- 配置使用二级缓存 -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <!--配置二级缓存的实现类 : EHCache -->
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <!-- 开启查询缓存  hibernate.cache.use_query_cache true -->
        <property name="hibernate.cache.use_query_cache">true</property>
    
        <!-- 引入ORM 映射文件 ,填写src之后的路径 -->
        <mapping resource="com/alice/hibernate02/vo/User.hbm.xml" />
        <mapping resource="com/alice/hibernate02/vo/Customer.hbm.xml" />
        <mapping resource="com/alice/hibernate02/vo/Order.hbm.xml" />
        
        
        <!-- 配置类缓存区中,缓存哪个类-->
        <class-cache usage="read-only" class="com.alice.hibernate02.vo.Customer"/>
        <class-cache usage="read-only" class="com.alice.hibernate02.vo.Order"/>
        <!-- 配置类缓存区中,缓存哪个集合
        collection: 完整类名.集合属性名
        -->
        <collection-cache usage="read-only" collection="com.alice.hibernate02.vo.Customer.orders"/>
    //演示:类缓存
    	@Test
    	public void test01(){
    		Session session = HibernateUtil.openSession();
    		Transaction tran = session.beginTransaction();
    		
    		Customer cus1 = (Customer) session.get(Customer.class, 6);
    		
    		//清空一级缓存中的内容
    		session.clear();
    		
    		Customer cus2 = (Customer) session.get(Customer.class, 6);
    		
    		//二级缓存在缓存数据时,并不是以对象的形式缓存. 缓存的是对象数据的散列. 每次从二级缓存拿 会在一级缓存中组装成对象.
    		System.out.println(cus1 == cus2);//true
    		
    		tran.commit();
    		session.close();
    	}
    

      

    5.配置ehcache自定义配置文件

    6、查询缓存

    1)  查询缓存又称为三级缓存(民间)

    2  )查询缓存默认不使用。需要手动开启

    3 ) 查询缓存:将HQL语句与 查询结果进行绑定。通过HQL相同语句可以缓存内容。

           默认情况Query对象只将查询结果存放在一级和二级缓存,不从一级或二级缓存获取。

           查询缓存就是让Query可以从二级缓存获得内容。

    步骤一:开启查询缓存

    步骤二:在查询query对象,设置缓存内容(注意:存放和查询 都需要设置)

    package com.alice.hibernate02.second;
    
    
    import java.util.List;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test;
    
    import com.alice.hibernate02.util.HibernateUtil;
    import com.alice.hibernate02.vo.Customer;
    
    public class Demo02 {
        
        @Test
        public void test01(){
            Session session = HibernateUtil.openSession();
            Transaction tran = session.beginTransaction();
            //使用二级(查询)缓存
             // 查询时,会先从二级缓存中取结果.
             // 取不到就执行语句,将结果放入二级查询缓存中
            Query query1 = session.createQuery("from Customer");
            query1.setCacheable(true);
            
            List<Customer> list1 = query1.list();
            
            session.clear();
            
            Query query2 = session.createQuery("select c from Customer c");
            query2.setCacheable(true);
            
            List<Customer> list2 = query2.list();
            for(Customer c:list2){
                System.out.println(c);
            }
            
            tran.commit();
            session.close();
        }
    }

    6、时间戳区

    时间戳:任何操作都在时间戳中记录操作时间

    //演示:时间戳
    public class Demo03 {
    	@Test
    	public void test01() {
    		Session session = HibernateUtil.openSession();
    		Transaction tran = session.beginTransaction();
    
    		Customer cus1 = (Customer) session.get(Customer.class, 6);
    
    		session.createQuery("update Customer set name=:name where id = :id")
    				.setString("name", "roese").setInteger("id", 6).executeUpdate();
    
    		session.clear();
    
    		Customer cus2 = (Customer) session.get(Customer.class, 6);
    
    		tran.commit();
    		session.close();
    	}
    }
    

      7、 ehcache配置文件

      <diskStore path="java.io.tmpdir"/>  设置临时文件存放位置。(缓存一般内存,一定程度时,写入硬盘。)

    1  缓存详细设置

           <defaultCache> 所有的缓存对象默认的配置

           <cache name="类"> 指定对象单独配置

    2  参数设置

    maxElementsInMemory="10000"  内存最大数

    eternal="false"  是否永久(内存常驻留)

    timeToIdleSeconds="120"

    timeToLiveSeconds="120"

    overflowToDisk="true"  内存满了,是否写入到硬盘

    maxElementsOnDisk="10000000"  硬盘最大数

    diskPersistent="false"  关闭JVM,是否将内存保存硬盘中

    diskExpiryThreadIntervalSeconds="120"  轮询

    memoryStoreEvictionPolicy="LRU"

           Least Recently Used (specified as LRU).

           First In First Out (specified as FIFO)

           Less Frequently Used (specified as LFU)

  • 相关阅读:
    HDOJ_ACM_超级楼梯
    HDOJ_ACM_下沙的沙子有几粒?
    杭电_ACM_How Many Trees
    HDOJ_ACM_Tiling_easy version
    HDOJ_ACM_母牛的故事
    HDOJ_ACM_小兔的棋盘
    HDOJ_ACM_一只小蜜蜂
    杭电_ACM_Count the Trees
    HDOJ_ACM_折线分割平面
    Sun Solaris下JAVA以及JSP开发环境的配制小记
  • 原文地址:https://www.cnblogs.com/snowwang/p/6134017.html
Copyright © 2011-2022 走看看