Hibernate Session缓存
Session缓存:
在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期
Session 缓存可减少 Hibernate 应用程序访问数据库的频率。
1:利用反射查询对象
News news =(News) session.get(News.class, 1); System.out.println(news); News news2 =(News) session.get(News.class, 1); System.out.println(news2);
但是只出现了一条SQL
这就是session缓存。也叫一级缓存。位于缓存中的数据叫做持久化对象。
站在持久化的角度。hibernate把对象分为4种状态:持久化。临时。游离。删除。
session缓存有三个方法。
1:flush()方法。
它的作用:缓存中的数据对象与数据库中数据对象保持一致。会发送SQL语句。但是不会提交事务。
为了确保数据一致。在以下会调用flush()方法。
1:显示的调用。session.flush();
2:事务提交的时候。会先调用flush()。然后再提交事务。
3:执行HQL或QBC查询。
4:若记录的ID是native(底层数据库自增的形式)生成的。在调用save()方法后。立即发送insert语句。
commit()方法的源码:在AbstractTransaction类中。
1 @Override 2 public void commit() throws HibernateException { 3 if ( localStatus != LocalStatus.ACTIVE ) { 4 throw new TransactionException( "Transaction not successfully started" ); 5 } 6 7 LOG.debug( "committing" ); 8 9 beforeTransactionCommit(); 10 11 try { 12 doCommit(); 13 localStatus = LocalStatus.COMMITTED; 14 afterTransactionCompletion( Status.STATUS_COMMITTED ); 15 } 16 catch ( Exception e ) { 17 localStatus = LocalStatus.FAILED_COMMIT; 18 afterTransactionCompletion( Status.STATUS_UNKNOWN ); 19 throw new TransactionException( "commit failed", e ); 20 } 21 finally { 22 invalidate(); 23 afterAfterCompletion(); 24 } 25 }
在12行提交事务。第9行是 beforeTransactionCommit();
在提交事务前干点什么?
在JdbcTransaction类中。
1 protected void beforeTransactionCommit() { 2 transactionCoordinator().sendBeforeTransactionCompletionNotifications( this ); 3 4 // basically, if we are the driver of the transaction perform a managed flush prior to 5 // physically committing the transaction 6 if ( isDriver && !transactionCoordinator().getTransactionContext().isFlushModeNever() ) { 7 // if an exception occurs during flush, user must call rollback() 8 transactionCoordinator().getTransactionContext().managedFlush(); 9 } 10 11 if ( isDriver ) { 12 transactionCoordinator().getTransactionContext().beforeTransactionCompletion( this ); 13 } 14 }
在第8行会管理事务。TransactionContext 类中
public void managedFlush();
SessionImpl 类中
1 public void managedFlush() { 2 if ( isClosed() ) { 3 LOG.trace( "Skipping auto-flush due to session closed" ); 4 return; 5 } 6 LOG.trace( "Automatically flushing session" ); 7 flush(); 8 }
在第7行进行flush()方法的调用。
2:refresh():强制使缓存中的一个对象状态与数据库中记录的对象状态一致。
打上断点。然后现在去数据库中修改数据。
得到的数据还是一样的。
使用refresh()方法
这是因为Hibernate在MySQL中的隔离级别。默认是可重复读。虽然重新读了一个select。但是还是读的以前的那个select语句。
在hibernate.cfg.xml中
1 <!-- 设置隔离级别 --> 2 <property name="connection.isolation">2</property>
1. READ UNCOMMITED 读未提交数据
2. READ COMMITED 读已提交数据
4. REPEATABLE READ 可重复读
8. SERIALIZEABLE 串行化
3:clear() 清理缓存