入口
dubbo接口,调用service类的事务业务方法。
spring事务拦截器-开始
。。。
最后一步
MethodProxy
public Object invoke(Object obj, Object[] args) throws Throwable {
try {
this.init();
MethodProxy.FastClassInfo fci = this.fastClassInfo;
return fci.f1.invoke(fci.i1, obj, args); //调用业务方法
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
} catch (IllegalArgumentException var5) {
if (this.fastClassInfo.i1 < 0) {
throw new IllegalArgumentException("Protected method: " + this.sig1);
} else {
throw var5;
}
}
}
service类的业务方法
包含多个sql
业务方法里的每个sql都会被拦截器拦截
CglibAopProxy
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// May be null Get as late as possible to minimize the time we
// "own" the target, in case it comes from a pool.
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
retVal = methodProxy.invoke(target, args);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); //
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
最后一步,和service一样,然后就进入dao的方法。
dao的方法
业务dao的方法
公司封装的hibernate基础公共dao
protected Object getUniqueResult(final QueryHelper helper) {
String ObjectName = null == this.getModelClass() ? "" : this.getModelClass().getName() + ".";
String methodName = "getUniqueResult";
Transaction t = Cat.newTransaction("SQL", ObjectName + methodName);
String queryStr = "NULL";
if (helper != null && helper.getHql() != null) {
queryStr = helper.getHql().toString();
}
Event methodEvent = this.logEvent("SQL.Method", "SELECT");
String Database = this.getDBConnectionUrl();
Event DBEvent = this.logEvent("SQL.Database", Database);
Event typeEvent = this.logEvent("SQL.Type", "hibernate");
t.addChild(methodEvent);
t.addChild(DBEvent);
t.addChild(typeEvent);
t.addData(queryStr);
Object var11;
try {
Object object = this.getHibernateTemplate().execute(new HibernateCallback() { //查询
public Object doInHibernate(Session session) throws HibernateException, SQLException {
return helper.getUniqueResult(session); //回调
}
});
t.setStatus("0");
var11 = object;
} catch (Exception var15) {
Cat.logError(var15);
t.setStatus(var15.getClass().getSimpleName());
throw var15;
} finally {
t.complete();
}
return var11;
}
hibernate查询
HibernateTemplate
/**
* Execute the action specified by the given action object within a Session.
* @param action callback object that specifies the Hibernate action
* @param enforceNewSession whether to enforce a new Session for this template
* even if there is a pre-bound transactional Session
* @param enforceNativeSession whether to enforce exposure of the native
* Hibernate Session to callback code
* @return a result object returned by the action, or {@code null}
* @throws org.springframework.dao.DataAccessException in case of Hibernate errors
*/
protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)
throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Session session = (enforceNewSession ?
SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
boolean existingTransaction = (!enforceNewSession &&
(!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));
if (existingTransaction) {
logger.debug("Found thread-bound Session for HibernateTemplate");
}
FlushMode previousFlushMode = null;
try {
previousFlushMode = applyFlushMode(session, existingTransaction);
enableFilters(session);
Session sessionToExpose =
(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session)); //创建会话对象
T result = action.doInHibernate(sessionToExpose); //回调
flushIfNecessary(session, existingTransaction);
return result;
}
catch (HibernateException ex) {
throw convertHibernateAccessException(ex);
}
catch (SQLException ex) {
throw convertJdbcAccessException(ex);
}
catch (RuntimeException ex) {
// Callback code threw application exception...
throw ex;
}
finally {
if (existingTransaction) {
logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
else {
// Never use deferred close for an explicitly new Session.
if (isAlwaysUseNewSession()) {
SessionFactoryUtils.closeSession(session);
}
else {
SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
}
}
}
}
回调
HqlHelper
public Object getUniqueResult(Session session) {
return this.getQuery(session).uniqueResult(); //查询
}
HibernateTemplate
/**
* Invocation handler that suppresses close calls on Hibernate Sessions.
* Also prepares returned Query and Criteria objects.
* @see org.hibernate.Session#close
*/
private class CloseSuppressingInvocationHandler implements InvocationHandler {
private final Session target;
public CloseSuppressingInvocationHandler(Session target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Invocation on Session interface coming in...
if (method.getName().equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0]);
}
else if (method.getName().equals("hashCode")) {
// Use hashCode of Session proxy.
return System.identityHashCode(proxy);
}
else if (method.getName().equals("close")) {
// Handle close method: suppress, not valid.
return null;
}
// Invoke method on target Session.
try {
Object retVal = method.invoke(this.target, args); //
// If return value is a Query or Criteria, apply transaction timeout.
// Applies to createQuery, getNamedQuery, createCriteria.
if (retVal instanceof Query) {
prepareQuery(((Query) retVal)); //
}
if (retVal instanceof Criteria) {
prepareCriteria(((Criteria) retVal));
}
return retVal;
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
}
/**
* Prepare the given Query object, applying cache settings and/or
* a transaction timeout.
* @param queryObject the Query object to prepare
* @see #setCacheQueries
* @see #setQueryCacheRegion
* @see SessionFactoryUtils#applyTransactionTimeout
*/
protected void prepareQuery(Query queryObject) {
if (isCacheQueries()) { //false,不是从缓存查询
queryObject.setCacheable(true);
if (getQueryCacheRegion() != null) {
queryObject.setCacheRegion(getQueryCacheRegion());
}
}
if (getFetchSize() > 0) {
queryObject.setFetchSize(getFetchSize());
}
if (getMaxResults() > 0) {
queryObject.setMaxResults(getMaxResults());
}
SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
}
AbstractQueryImpl
public Object uniqueResult() throws HibernateException {
return uniqueElement(this.list()); //从查询集合里取第一个数据
}
QueryImpl
public List list() throws HibernateException {
this.verifyParameters();
Map namedParams = this.getNamedParams();
this.before();
List var2;
try {
var2 = this.getSession().list(this.expandParameterLists(namedParams), this.getQueryParameters(namedParams)); //查询
} finally {
this.after();
}
return var2;
}
public List list(String query, QueryParameters queryParameters) throws HibernateException {
this.errorIfClosed();
this.checkTransactionSynchStatus();
queryParameters.validateParameters();
HQLQueryPlan plan = this.getHQLQueryPlan(query, false);
this.autoFlushIfRequired(plan.getQuerySpaces());
List results = CollectionHelper.EMPTY_LIST;
boolean success = false;
++this.dontFlushFromFind;
try {
results = plan.performList(queryParameters, this); //查询
success = true;
} finally {
--this.dontFlushFromFind;
this.afterOperation(success);
}
return results;
}
HQLQueryPlan
public List performList(QueryParameters queryParameters, SessionImplementor session) throws HibernateException {
if (log.isTraceEnabled()) {
log.trace("find: " + this.getSourceQuery());
queryParameters.traceParameters(session.getFactory());
}
boolean hasLimit = queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
boolean needsLimit = hasLimit && this.translators.length > 1;
QueryParameters queryParametersToUse;
if (needsLimit) {
log.warn("firstResult/maxResults specified on polymorphic query; applying in memory!");
RowSelection selection = new RowSelection();
selection.setFetchSize(queryParameters.getRowSelection().getFetchSize());
selection.setTimeout(queryParameters.getRowSelection().getTimeout());
queryParametersToUse = queryParameters.createCopyUsing(selection);
} else {
queryParametersToUse = queryParameters;
}
List combinedResults = new ArrayList();
IdentitySet distinction = new IdentitySet();
int includedCount = -1;
for(int i = 0; i < this.translators.length; ++i) {
List tmp = this.translators[i].list(session, queryParametersToUse); //查询
if (needsLimit) {
int first = queryParameters.getRowSelection().getFirstRow() == null ? 0 : queryParameters.getRowSelection().getFirstRow();
int max = queryParameters.getRowSelection().getMaxRows() == null ? -1 : queryParameters.getRowSelection().getMaxRows();
int size = tmp.size();
for(int x = 0; x < size; ++x) {
Object result = tmp.get(x);
if (distinction.add(result)) {
++includedCount;
if (includedCount >= first) {
combinedResults.add(result);
if (max >= 0 && includedCount > max) {
return combinedResults;
}
}
}
}
} else {
combinedResults.addAll(tmp);
}
}
return combinedResults;
}
QueryTranslatorImpl
public List list(SessionImplementor session, QueryParameters queryParameters) throws HibernateException {
this.errorIfDML();
QueryNode query = (QueryNode)this.sqlAst;
boolean hasLimit = queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
boolean needsDistincting = (query.getSelectClause().isDistinct() || hasLimit) && this.containsCollectionFetches();
QueryParameters queryParametersToUse;
if (hasLimit && this.containsCollectionFetches()) {
log.warn("firstResult/maxResults specified with collection fetch; applying in memory!");
RowSelection selection = new RowSelection();
selection.setFetchSize(queryParameters.getRowSelection().getFetchSize());
selection.setTimeout(queryParameters.getRowSelection().getTimeout());
queryParametersToUse = queryParameters.createCopyUsing(selection);
} else {
queryParametersToUse = queryParameters;
}
List results = this.queryLoader.list(session, queryParametersToUse); //查询
if (needsDistincting) {
int includedCount = -1;
int first = hasLimit && queryParameters.getRowSelection().getFirstRow() != null ? queryParameters.getRowSelection().getFirstRow() : 0;
int max = hasLimit && queryParameters.getRowSelection().getMaxRows() != null ? queryParameters.getRowSelection().getMaxRows() : -1;
int size = ((List)results).size();
List tmp = new ArrayList();
IdentitySet distinction = new IdentitySet();
for(int i = 0; i < size; ++i) {
Object result = ((List)results).get(i);
if (distinction.add(result)) {
++includedCount;
if (includedCount >= first) {
tmp.add(result);
if (max >= 0 && includedCount - first >= max - 1) {
break;
}
}
}
}
results = tmp;
}
return (List)results;
}
Loader
protected List doList(SessionImplementor session, QueryParameters queryParameters) throws HibernateException {
boolean stats = this.getFactory().getStatistics().isStatisticsEnabled();
long startTime = 0L;
if (stats) {
startTime = System.currentTimeMillis();
}
List result;
try {
result = this.doQueryAndInitializeNonLazyCollections(session, queryParameters, true); //查询
} catch (SQLException var8) {
throw JDBCExceptionHelper.convert(this.factory.getSQLExceptionConverter(), var8, "could not execute query", this.getSQLString());
}
if (stats) {
this.getFactory().getStatisticsImplementor().queryExecuted(this.getQueryIdentifier(), result.size(), System.currentTimeMillis() - startTime);
}
return result;
}
AbstractBatcher
public ResultSet getResultSet(PreparedStatement ps) throws SQLException {
ResultSet rs = ps.executeQuery(); //查询
this.resultSetsToClose.add(rs);
this.logOpenResults();
return rs;
}
dbcp
hibernate委托给了dbcp
DelegatingPreparedStatement
public ResultSet executeQuery() throws SQLException {
this.checkOpen();
try {
return DelegatingResultSet.wrapResultSet(this, ((PreparedStatement)this._stmt).executeQuery()); //查询
} catch (SQLException var2) {
this.handleException(var2);
throw new AssertionError();
}
}
oracle
说明hibernate的sql,已经被发送到oracle,而不是从缓存
public ResultSet executeQuery() throws SQLException {
return this.preparedStatement.executeQuery();
}
回到应用,从结果集合取第一个数据
static Object uniqueElement(List list) throws NonUniqueResultException { //从集合里获取第一个数据
int size = list.size();
if (size == 0) {
return null;
} else {
Object first = list.get(0);
for(int i = 1; i < size; ++i) {
if (list.get(i) != first) {
throw new NonUniqueResultException(list.size());
}
}
return first;
}
}
调用栈
executeQuery:1495, OraclePreparedStatementWrapper (oracle.jdbc.driver)
executeQuery:96, DelegatingPreparedStatement (org.apache.commons.dbcp) [2]
executeQuery:96, DelegatingPreparedStatement (org.apache.commons.dbcp) [1]
getResultSet:208, AbstractBatcher (org.hibernate.jdbc)
getResultSet:1953, Loader (org.hibernate.loader)
doQuery:802, Loader (org.hibernate.loader)
doQueryAndInitializeNonLazyCollections:274, Loader (org.hibernate.loader)
doList:2542, Loader (org.hibernate.loader)
listIgnoreQueryCache:2276, Loader (org.hibernate.loader)
list:2271, Loader (org.hibernate.loader)
list:316, CustomLoader (org.hibernate.loader.custom)
listCustomQuery:1842, SessionImpl (org.hibernate.impl)
list:165, AbstractSessionImpl (org.hibernate.impl)
list:157, SQLQueryImpl (org.hibernate.impl)
listBySql:23, QueryHelper (hikefa.core.spring.util)
doInHibernate:1423, CatBaseDaoHibernateImpl$25 (com.xxx.log.integration.hibernate)
doExecute:406, HibernateTemplate (org.springframework.orm.hibernate3)
execute:339, HibernateTemplate (org.springframework.orm.hibernate3)
getListBySql:1421, CatBaseDaoHibernateImpl (com.xxx.log.integration.hibernate)
queryUrmtmFee:51, UrmtmFeeBaseDao (xxx.qrcode.register.dao.impl)
invoke:-1, UrmtmFeeBaseDao$$FastClassByCGLIB$$2b8e3f7d (xxx.qrcode.register.dao.impl)
invoke:204, MethodProxy (org.springframework.cglib.proxy)
invokeJoinpoint:698, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:150, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:80, MethodInvocationProceedingJoinPoint (org.springframework.aop.aspectj)
around:38, MethodExecTimeAspect (xxx.qrcode.register.util)
invoke:-1, GeneratedMethodAccessor258 (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:606, Method (java.lang.reflect)
invokeAdviceMethodWithGivenArgs:621, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invokeAdviceMethod:610, AbstractAspectJAdvice (org.springframework.aop.aspectj)
invoke:65, AspectJAroundAdvice (org.springframework.aop.aspectj)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
invoke:91, ExposeInvocationInterceptor (org.springframework.aop.interceptor)
proceed:172, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:631, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
queryUrmtmFee:-1, UrmtmFeeBaseDao$$EnhancerByCGLIB$$14ebc711 (xxx.qrcode.register.dao.impl)
getFee:219, QrcodeMerQueryServer (xxx.qrcode.register.remoteserver.impl)
queryMerchantInfo:75, QrcodeMerQueryServer (xxx.qrcode.register.remoteserver.impl)
invokeMethod:-1, Wrapper28 (com.alibaba.dubbo.common.bytecode)
doInvoke:47, JavassistProxyFactory$1 (com.alibaba.dubbo.rpc.proxy.javassist)
invoke:76, AbstractProxyInvoker (com.alibaba.dubbo.rpc.proxy)
invoke:52, DelegateProviderMetaDataInvoker (com.alibaba.dubbo.config.invoker)
invoke:56, InvokerWrapper (com.alibaba.dubbo.rpc.protocol)
invoke:11, AppNameAppendFilter (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:62, ExceptionFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:42, TimeoutFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:60, ExecuteLimitFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:75, MonitorFilter (com.alibaba.dubbo.monitor.support)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:78, TraceFilter (com.alibaba.dubbo.rpc.protocol.dubbo.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:84, AccessLogExtFilter (xxx.qrcode.common.filter.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:82, CatTransaction (com.xxx.log.rpc.dubbo)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:73, ContextFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:138, GenericFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, ClassLoaderFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
invoke:38, EchoFilter (com.alibaba.dubbo.rpc.filter)
invoke:72, ProtocolFilterWrapper$1 (com.alibaba.dubbo.rpc.protocol)
reply:104, DubboProtocol$1 (com.alibaba.dubbo.rpc.protocol.dubbo)
handleRequest:96, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:173, HeaderExchangeHandler (com.alibaba.dubbo.remoting.exchange.support.header)
received:51, DecodeHandler (com.alibaba.dubbo.remoting.transport)
run:57, ChannelEventRunnable (com.alibaba.dubbo.remoting.transport.dispatcher)
runWorker:1145, ThreadPoolExecutor (java.util.concurrent)
run:615, ThreadPoolExecutor$Worker (java.util.concurrent)
run:745, Thread (java.lang)
总结
1、每个sql都被发送到了oracle,而不是从hibernate缓存读写数据,最后service类的业务方法结束的时候,提交事务,oracle数据更新永久生效,即对其他事务都生效可见。
调试源码的过程中,走到了oracle,也证明sql被发送到了oracle,即是从oracle数据库读写数据,而不是从hibernate缓存。
2、流程
应用业务代码(service类的业务方法,包含多个sql)——》spring事务——》dao的方法(单个sql)——》hibernate——》连接池dbcp——》jdbc-oracle——》数据库oracle。
每一层只管一件事,
1)spring事务,只负责事务开始和提交。
2)hibernate,就是会话连接,本质其实就是jdbc的Connection对象。
3)连接池dbcp,负责获取数据库连接。
然后,每一层执行的时候,都是由上一层委托给下一层。