zoukankan      html  css  js  c++  java
  • Hibernate学习之一级缓存

    © 版权声明:本文为博主原创文章,转载请注明出处

    Hibernate缓存:

      - 缓存是为了降低应用程序对物理数据源访问的频次,从而提供应用程序的运行性能的一种策略

      - Hibernate缓存是提升和优化Hibernate执行效率的重要手段

    工作原理:

      1. 应用程序读取缓存数据

      2. 缓存命中则直接返回数据

      3. 缓存未命中则去数据库中查询数据,然后将数据放入缓存中并返回数据

    一级缓存:

      1. Hibernate一级缓存又称为“Session缓存”、“会话级缓存”

      2. 通过Session从数据库查询实体时会把实体从内存中取出来,下一查询统一实体时不再从数据库获取,而是从内存中获取

      3. 一级缓存的声明周期和Session相同;Session销毁,它也销毁

      4. 一级缓存的数据可使用范围在当前会话之内

    API:

      1. 一级缓存无法取消,用两个方法管理

        - evict():用于将对象从Session的一级缓存中清除

        - clear():用于将一级缓存中的所有对象清除

      2. 相关方法

        - query.list()

        - query.iterate()

    实例:

    1.项目结构

    2.pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      
      	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>org.struts</groupId>
    	<artifactId>Hibernate-PrimaryBuffer</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<hibernate.version>5.1.7.Final</hibernate.version>
    	</properties>
    
    	<dependencies>
    		<!-- Junit -->
    		<dependency>
    			<groupId>junit</groupId>
    			<artifactId>junit</artifactId>
    			<version>4.12</version>
    			<scope>test</scope>
    		</dependency>
    		<!-- Hibernate -->
    		<dependency>
    		    <groupId>org.hibernate</groupId>
    		    <artifactId>hibernate-core</artifactId>
    		    <version>${hibernate.version}</version>
    		</dependency>
    		<!-- MySQL -->
    		<dependency>
    		    <groupId>mysql</groupId>
    		    <artifactId>mysql-connector-java</artifactId>
    		    <version>5.1.42</version>
    		</dependency>
    	</dependencies>
    	
    </project>

    3.Student.java

    package org.hibernate.model;
    
    import java.util.Date;
    
    /**
     * 学生实体类
     *
     */
    public class Student {
    
    	private long id;// 学号
    	private String username;// 姓名
    	private Date birthday;// 生日
    	private String sex;// 性别
    	
    	public Student() {
    	}
    	public Student(long id, String username, Date birthday, String sex) {
    		this.id = id;
    		this.username = username;
    		this.birthday = birthday;
    		this.sex = sex;
    	}
    	public long getId() {
    		return id;
    	}
    	public void setId(long id) {
    		this.id = id;
    	}
    	public String getUsername() {
    		return username;
    	}
    	public void setUsername(String username) {
    		this.username = username;
    	}
    	public Date getBirthday() {
    		return birthday;
    	}
    	public void setBirthday(Date birthday) {
    		this.birthday = birthday;
    	}
    	public String getSex() {
    		return sex;
    	}
    	public void setSex(String sex) {
    		this.sex = sex;
    	}
    	
    }

    4.Student.hbm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd" >
    <hibernate-mapping>
    
    	<class name="org.hibernate.model.Student" table="STUDENT">
    		<id name="id" type="java.lang.Long">
    			<column name="ID"/>
    			<generator class="assigned"/>
    		</id>
    		<property name="username" type="java.lang.String">
    			<column name="USERNAME"/>
    		</property>
    		<property name="birthday" type="date">
    			<column name="BIRTHDAY"/>
    		</property>
    		<property name="sex" type="java.lang.String">
    			<column name="SEX"/>
    		</property>
    	</class>
    
    </hibernate-mapping>

    5.hibernate.cfg.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
    
    	<!-- 配置SessionFactory -->
    	<session-factory>
    		<!-- 配置数据库连接信息 -->
    		<property name="connection.username">root</property>
    		<property name="connection.password">***</property>
    		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    		<property name="connection.url">
    			jdbc:mysql:///hibernate?useSSL=true&amp;characterEncoding=UTF-8
    		</property>
    		<!-- 常用设置 -->
    		<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property><!-- 方言 -->
    		<property name="show_sql">true</property><!-- 是否展示SQL -->
    		<property name="format_sql">false</property><!-- 格式化SQL -->
    		<property name="hbm2ddl.auto">update</property><!-- 自动创建表结构 -->
    		<!-- 引入映射文件 -->
    		<mapping resource="hbm/Student.hbm.xml"/>
    	</session-factory>
    
    </hibernate-configuration>

    6.TestPrimartBuffer.java

    package org.hibernate.test;
    
    import java.util.Date;
    import java.util.Iterator;
    import java.util.List;
    
    import org.hibernate.Query;
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.model.Student;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    public class TestPrimaryBuffer {
    	
    	private SessionFactory sessionFactory;
    	private Session session;
    	private Transaction transaction;
    	
    	@Before
    	public void before() {
    		
    		sessionFactory = new Configuration().configure().buildSessionFactory();// 创建会话工厂对象
    		session = sessionFactory.openSession();// 创建会话
    		transaction = session.beginTransaction();// 开始事务
    		
    	}
    	
    	@After
    	public void after() {
    		
    		transaction.commit();// 提交事务
    		session.close();// 关闭会话
    		sessionFactory.close();// 关闭会话工厂
    		
    	}
    	
    	/**
    	 * 初始化数据库
    	 */
    	@Test
    	public void init() {
    	
    		Student student = new Student(1, "张三", new Date(), "男");
    		session.save(student);
    		student = new Student(2, "李四", new Date(), "男");
    		session.save(student);
    		student = new Student(3, "王五", new Date(), "男");
    		session.save(student);
    		
    	}
    	
    	/**
    	 * 同一个session
    	 */
    	@Test
    	public void testSameSession() {
    		
    		Student student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    		student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    	}
    	
    	/**
    	 * 不同session
    	 */
    	@Test
    	public void testDiffSession() {
    		
    		Student student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    		session = sessionFactory.openSession();
    		student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    	}
    	
    	/**
    	 * Evict,同一个session
    	 */
    	@Test
    	public void testEvict() {
    		
    		Student student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    		session.evict(student);
    		
    		student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    	}
    	
    	/**
    	 * Clear,同一个session
    	 */
    	@Test
    	public void testClear() {
    		
    		Student student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    		session.clear();
    		
    		student = session.get(Student.class, 1L);
    		System.out.println(student.getUsername());
    		
    	}
    
    	/**
    	 * Query
    	 */
    	@Test
    	@SuppressWarnings("unchecked")
    	public void testQuery() {
    		
    		Query query = session.createQuery("from Student");
    		List<Student> list = query.list();
    		for (Student s: list) {
    			System.out.println(s.getUsername());
    		}
    		
    		System.out.println();
    		
    		list = query.list();
    		for (Student s: list) {
    			System.out.println(s.getUsername());
    		}
    		
    	}
    	
    	/**
    	 * Interate
    	 */
    	@Test
    	@SuppressWarnings("unchecked")
    	public void testIterate() {
    		
    		Query query = session.createQuery("from Student");
    		List<Student> list = query.list();
    		for (Student s: list) {
    			System.out.println(s.getUsername());
    		}
    		
    		System.out.println();
    		
    		Iterator<?> iterator = query.iterate();
    		while (iterator.hasNext()) {
    			Student s = (Student) iterator.next();
    			System.out.println(s.getUsername());
    		}
    		
    	}
    	
    	/**
    	 * Interate2
    	 */
    	@Test
    	public void testIterate2() {
    		
    		Query query = session.createQuery("from Student");
    		Iterator<?> iterator = query.iterate();
    		while (iterator.hasNext()) {
    			Student s = (Student) iterator.next();
    			System.out.println(s.getUsername());
    		}
    		
    	}
    	
    }

    7.效果预览(首先执行init()方法进行数据库表的初始化

      7.1 执行testSameSession()方法

        说明:同一个Session中查询同一对象使用缓存,执行一次查询操作

      7.2 执行testDiffSession()方法

        说明:不同Session中查询同一对象没有使用缓存,执行多次查询操作

      7.3 执行testEvict()方法

        说明:同一Session中,由于使用evict()方法从缓存中清除了Student对象,因此也需查询多次

      7.4 执行testClear()方法

        说明:同一Session中,由于使用clear()方法清除了缓存中的所有对象,因此也需查询多次

      7.5 执行testQuery()方法

        说明:在同一Session中查询同一对象,依然执行了两次SQL,说明query.list()方法不使用缓存

      7.6 执行testIterate()方法

      7.7 执行testIterate2()方法

        说明:从7.6和7.7的结果可以得出,query.iterate()方法使用缓存,但是iterate()方法先从数据中查询所有的id,然后通过id去缓存中查找;若查找失败,则根据id去数据库查询详细信息

    8.总结:

      1. 同一个session对象,多次查询同一个对象,因为缓存只会执行一次查询操作,查询效率较快

      2. 不同Session对象,多次查询同一对象,不存在缓存会多次执行查询操作,查询效率较慢

      3. query.list()虽然在同一个Session中,但是不会使用缓存

      4. query.iterate()在同一个Session中会使用缓存。但是iterate()会先从数据库中查询所有的id,然后通过id去缓存中查询对应对象;

        若缓存中不存在该id对应的对象,则会根据id去数据库中查询

    参考:http://www.imooc.com/video/9016

  • 相关阅读:
    LeetCode "Median of Two Sorted Arrays"
    LeetCode "Distinct Subsequences"
    LeetCode "Permutation Sequence"

    LeetCode "Linked List Cycle II"
    LeetCode "Best Time to Buy and Sell Stock III"
    LeetCode "4Sum"
    LeetCode "3Sum closest"
    LeetCode "3Sum"
    LeetCode "Container With Most Water"
  • 原文地址:https://www.cnblogs.com/jinjiyese153/p/6930077.html
Copyright © 2011-2022 走看看