http://developer.51cto.com/art/200906/130045.htm
网上流传的很老的一段文字:
红框标记的文字使用hibernate 源码来解释:
hibernate-3.6.0.final/core/src/main/java/org/hibernate/loader/Loader.java
请查看代码Loader.java 1341行代码:
/***
* Resolve any IDs for currently loaded objects, duplications within the
* <tt>ResultSet</tt>, etc. Instantiate empty objects to be initialized from the
* <tt>ResultSet</tt>. Return an array of objects (a row of results) and an
* array of booleans (by side-effect) that determine whether the corresponding
* object should be initialized.
*/
private Object[] getRow(
final ResultSet rs,
final Loadable[] persisters,
final EntityKey[] keys,
final Object optionalObject,
final EntityKey optionalObjectKey,
final LockMode[] lockModes,
final List hydratedObjects,
final SessionImplementor session)
throws HibernateException, SQLException {
final int cols = persisters.length;
final EntityAliases[] descriptors = getEntityAliases();
if ( log.isDebugEnabled() ) {
log.debug(
"result row: " +
StringHelper.toString( keys )
);
}
final Object[] rowResults = new Object[cols];
for ( int i = 0; i < cols; i++ ) {
Object object = null;
EntityKey key = keys[i];
if ( keys[i] == null ) {
//do nothing
}
else {//如果对象已经加载,则直接从session缓存中获取
//If the object is already loaded, return the loaded one
object = session.getEntityUsingInterceptor( key );
if ( object != null ) {
//its already loaded so don't need to hydrate it
instanceAlreadyLoaded(
rs,
i,
persisters[i],
key,
object,
lockModes[i],
session
);
}
else {//没有直接从数据库查询
object = instanceNotYetLoaded(
rs,
i,
persisters[i],
descriptors[i].getRowIdAlias(),
key,
lockModes[i],
optionalObjectKey,
optionalObject,
hydratedObjects,
session
);
}
}
rowResults[i] = object;
}
return rowResults;
}
举个例:
账户对象:Account.java
public class Account{
private Long Id;
private Long balance;
}
两个方法:
//通过用户编号查询用户
getAccountById();
//DML操作更新账户余额
updateAccountBalance();
session.createQuery("update Account a set a.balance=? where a.id = ?").setParameter(0, -100).setParameter(1, 1)
.executeUpdate();
在AccountService中同一个事务中执行如下操作:
场景1
(1) Account account = getAccountById(1);
//更新编号1的余额
(2) updateAccountBalance();
//再次查询
(3)account = getAccountById(1);
此时account对象的余额是没有改变的,因为结果来自session缓存
//更新编号1的余额
(2) updateAccountBalance();
//再次查询
(3)account = getAccountById(1);
此时account对象的余额是没有改变的,因为结果来自session缓存
如果将Hibernate 中设置show_sql = true ,
(1)和(3)都会输入查询SQL,需注意是(3)虽然输出了SQL但数据并不是来自数据库。
场景2
//更新编号1的余额
updateAccountBalance();
//再次查询
Account account = getAccountById(1);
此时account对象的余额是更新后的,因为结果来源数据库
updateAccountBalance();
//再次查询
Account account = getAccountById(1);
此时account对象的余额是更新后的,因为结果来源数据库