什么是缓存:
缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取.
缓存的好处:
提升程序运行的效率.缓存技术是Hibernate的一个优化的手段.
Hibernate分成两个基本的缓存:
-
一级缓存:Session级别的缓存.一级缓存与session的生命周期一致.自带的.不可卸载.
-
二级缓存:SessionFactory级别的缓存.不是自带的.
一级缓存的生命周期和session的生命周期一致,当前sessioin一旦关闭,一级缓存就消失,session间不能共享一级缓存的数据,因此一级缓存也叫session级的缓存或事务级缓存。一级缓存只存实体对象的 ,它不会缓存一般的对象属性(查询缓存可以),即当获得对象后,就将该对象的缓存起来,如果在同一session中如果再去获取这个对象时,它会先判断缓存中有没有该对象的id,如果有就直接从缓存中取出,反之则去数据库中取,取的同时将该对象的缓存起来.
图解:
以下对hibernate的一级缓存进行代码测试:
1.1: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>
<session-factory>
<!-- 1. 数据库相关 -->
<property name="connection.username">root</property>
<property name="connection.password">123</property>
<property name="connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 连接MySQL数据库 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 2.配置本地事务(No CurrentSessionContext configured!) -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 3. 调试相关 -->
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<!-- 4.hibernate需要管理的数据库表对应的实体类映射文件 -->
<mapping resource="com/crud/one/entity/User.hbm.xml"></mapping>
</session-factory>
</hibernate-configuration>
1.2:实体类:User.java
public class User implements Serializable {
private Integer id;
private String userName;
private String userPwd;
public User() {
super();
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPwd() {
return userPwd;
}
public void setUserPwd(String userPwd) {
this.userPwd = userPwd;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", userPwd=" + userPwd + ", realName=" + realName
+ ", sex=" + sex + ", birthday=" + birthday + ", createDatetime=" + createDatetime + ", remark="
+ remark + "]";
}
}
1.3:User.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 table="t_hibernate_user" name="com.zking.one.entity.User">
<id name="id" type="java.lang.Integer" column="id">
<generator class="increment"></generator>
</id>
<property name="userName" type="java.lang.String" column="user_name"></property>
<property name="userPwd" type="java.lang.String" column="user_pwd"></property>
</class>
</hibernate-mapping>
1.4:测试方法:
public class Demo3 {
Session session= SessionFactoryUtils.getSession();
Transaction transaction = session.beginTransaction();
User user = session.get(User.class, 2); // 马上生成sql语句去查询
System.out.println(user.getRealName());
User user = session.get(User.class, 2); //不会发出sql,因为使用一级缓存的数据
System.out.println(user.getRealName());
// 3.提交事务
tx.commit();
// 4.关闭资源
session.close();
}
1.5:深入理解一级缓存中快照区:
public void demo4(){
// 1.创建Session
Session session= SessionFactoryUtils.getSession();
// 2.开启事务
Transaction transaction = session.beginTransaction();
// 获得一个持久态的对象.然后数据会分别放到一级缓存区和一级缓存快照区
User user = session.get(User.class, 2);
//user的名字改变了,一级缓存和快照区数据不一致,事务提交的时候发送SQL进行更新
user.setRealName("是不是傻");
// 3.提交事务
tx.commit();
// 4.关闭资源
session.close();
}
结论:向一级缓存存入数据的时候,放入一级缓存区和一级缓存快照区,当更新了一级缓存的数据的时候,事务一旦提交,比对一级缓存和快照区,如果数据一致,不更新,如果数据不一致,自动更新数据库.