记一次线上bug处理-mybatis一级缓存引起

本文介绍了一个关于MyBatis缓存导致线上定时任务计算金额出现错误的问题,并详细记录了定位问题的过程及最终解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

线上riskProvision定时任务,计算出的金额不对

定位问题:

查看日志

4.13 riskProvision
    2017-04-13 01:10:00.009 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] from current transaction
    2017-04-13 01:10:00.010 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] for iBATIS operation
    2017-04-13 01:10:00.010 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28]
    2017-04-13 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] from current transaction
    2017-04-13 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] for iBATIS operation
    2017-04-13 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28]
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Creating SqlSession with JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@43c10cbc]
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.Connection] DEBUG ooo Connection Opened
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SpringManagedTransaction] DEBUG JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@43c10cbc] will be managed by Spring
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1159e5ac]
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1159e5ac] for iBATIS operation
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.PreparedStatement] DEBUG ==> Executing: select sum(a.TRAN_AMT) from FIN_FUND_TRAN a join outcome_flow b on a.pt_no = b.pt_no and a.ser_no = b.bus_ser where '1' = a.TRAN_ACC and a.TRAN_REA = '1' and (b.RECO_STATE = 'U'or b.RECO_STATE = '0' or b.RECO_STATE = '5') and a.pt_no = ?
    2017-04-13 01:10:00.012 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.PreparedStatement] DEBUG ==> Parameters: 002(String)
    2017-04-13 01:10:00.014 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.ResultSet] DEBUG <== Columns: 1

好像也执行了,但是金额为什么和数据库的表里的不一致,再查整个的定时任务日志

4.13 cron
2017-04-13 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] from current transaction
2017-04-13 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] for iBATIS operation
2017-04-13 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28]
2017-04-13 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [net.tangdi.gxseas.service.AutoRecon] INFO === 日切日期:2017-04-07
2017-04-13 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [net.tangdi.gxseas.service.AutoRecon] INFO 任务号:A,任务执行步骤:A01,日切日期:20170407

4月13日应该执行4.12日的,为什么执行了4.07日的了?
查下数据库定时任务日期控制表也是4,12,诡异啊?
不对,日志为什么没有执行的sql记录呢?
异常的话也不应该执行下去啊,莫名其妙,陷入了无头绪的状态.
因为mybatis的调用时用的第三方小厂家封装框架,出于对于它的不信任,看起了源码,在BaseExecutor发现看玄机

public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
  ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
  if (closed) throw new ExecutorException("Executor was closed.");
 
  // Flush the internal cache is force is true
  if (ms.isFlushCacheRequired()) {
      clearLocalCache();
  }
  List list;
  try {
    queryStack++;
    CacheKey key = createCacheKey(ms, parameter, rowBounds);
    list = resultHandler == null ? (List) localCache.getObject(key) : null;
    if (list != null) {
      handleLocallyCachedOutputParameters(ms, key, parameter);
    } else {
      list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key);
    }
  } finally {
    queryStack--;
  }
  if (queryStack == 0) {
    for (DeferredLoad deferredLoad : deferredLoads) {
      deferredLoad.load();
    }
  }
  return list;
}

调用方resultHandler传入的默认全是null,说明它会缓存拿.
因为上面的sql都没有参数,key是一定的,所以第二次之后会查缓存,但是数据时会变的,造成缓存和数据库的数据不一致.
继续看mybatis源码,发现localCache是SqlSession的成员变量.那么就可以断定如果相同的sql在同一个SqlSession执行,就会命中缓存,为了证实我的猜想,继续翻日志

4.10 rishProvision
2017-04-10 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] from current transaction
2017-04-10 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] for iBATIS operation
2017-04-10 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.PreparedStatement] DEBUG ==> Executing: SELECT PT_NO, ACC_AMT, BOON_AMT, CUST_AMT, PRO_AMT, FEE_AMT, MX_AMT, LT_AMT, FXJT_AMT, PT_DEP_AMT, PRO_DEP_AMT, PROCOUNT, FINCOUNT, INVCOUNT, BOUNS_RATIO, LOANSUM_AMT, REPAY_RAT, LEVER_RAT, OVERDUE_RAT, OVERDUE_PRO_RAT, UPDATE_DATE, CORE_MANA_AMT, CORE_WAIT_AMT, PT_WAIT_AMT, CORE_RESULT, CORE_GUARA_AMT, CORE_BOND_WAIT_AMT, PT_BOND_WAIT_AMT, BOND_RESULT FROM PALTFORMACCOUNT
2017-04-10 01:10:00.011 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.PreparedStatement] DEBUG ==> Parameters:
2017-04-10 01:10:00.013 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.ResultSet] DEBUG <== Columns: PT_NO, ACC_AMT, BOON_AMT, CUST_AMT, PRO_AMT, FEE_AMT, MX_AMT, LT_AMT, FXJT_AMT, PT_DEP_AMT, PRO_DEP_AMT, PROCOUNT, FINCOUNT, INVCOUNT, BOUNS_RATIO, LOANSUM_AMT, REPAY_RAT, LEVER_RAT, OVERDUE_RAT, OVERDUE_PRO_RAT, UPDATE_DATE, CORE_MANA_AMT, CORE_WAIT_AMT, PT_WAIT_AMT, CORE_RESULT, CORE_GUARA_AMT, CORE_BOND_WAIT_AMT, PT_BOND_WAIT_AMT, BOND_RESULT
2017-04-10 01:10:00.014 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.ResultSet] DEBUG <== Row: 006, 17115160.20, 1316359.13, 12149570.66, 3057572.01, 1638003.75, 61413.78, 0.00, 208600.00, 1316359.13, 0.00, 61841, 61841, 5, 0.00, 453419406.77, 0.68, 0.070, 0.020, 0.000, 2015-09-07 10:07:26.292735, 19534686.720, null, null, 0, 851068.580, null, null, 0
2017-04-10 01:10:00.015 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28]
4.10 cron
2017-04-10 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28]
2017-04-10 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [net.tangdi.gxseas.service.AutoRecon] INFO 数据迁移到历史表,当前主机域名:znq133
2017-04-10 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] from current transaction
2017-04-10 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28] for iBATIS operation
2017-04-10 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.PreparedStatement] DEBUG ==> Executing: SELECT TO_CHAR(MAX(DT),'YYYY-MM-DD') FROM WORK_HOLIDAY WHERE TRASTATUS = '1'
2017-04-10 01:10:00.004 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.PreparedStatement] DEBUG ==> Parameters:
2017-04-10 01:10:00.005 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.ResultSet] DEBUG <== Columns: 1
2017-04-10 01:10:00.005 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [java.sql.ResultSet] DEBUG <== Row: 2017-04-07
2017-04-10 01:10:00.005 [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@12af9e28]

可以看出这几个SQLSession都是@12af9e28,且错误执行的数据就是这几天日志查处的,证实了我的想法

解决问题

了解下mybatis 的一级缓存,select语句默认开启,由MappedStatement的flushCache属性控制.
那么怎么把mybatis的一级缓存关闭呢?

官网说

 1.sql级别

<select id="queryTrastatusDateMax" resultType="String" flushCache="true">
    <![CDATA[ SELECT TO_CHAR(MAX(DT),'YYYY-MM-DD') FROM WORK_HOLIDAY WHERE TRASTATUS = '1' ]]>
</select>

 2.全局FlushCache

mybatis->configuration.xml->setting标签添加

<setting name="localCacheScope" value="STATEMENT" />

单条关闭不适合现在的存量项目,sql太多了,排查不方便,全局吧,一运行发现mybatis3.0.6版本不支持此属性

3.mybatis插件

全局拦截MappedStatement使flushCache=true

<plugins>
 <plugin interceptor="com.xxxxx.interceptor.FlushCacheInterceptor" />
</plugins>
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
 
import java.util.Properties;
 
/**
 * 关掉Mybatis所有查询的一级缓存
 * Created by mumubin 2017/4/13.
 */
@Intercepts(@Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class,
        RowBounds.class, ResultHandler.class}))
public class FlushCacheInterceptor implements Interceptor {
 
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        MappedStatement copy = copyMappedStatementFlushCache(mappedStatement);
        invocation.getArgs()[0] = copy;
        return invocation.proceed();
    }
 
    /**
     * 复制MappedStatement 并设置FlushCache=true
     * @param mappedStatement
     * @return
     */
    private MappedStatement copyMappedStatementFlushCache(MappedStatement mappedStatement) {
        MappedStatement.Builder builder = new MappedStatement.Builder(mappedStatement.getConfiguration(),
                mappedStatement.getId(), mappedStatement.getSqlSource(), mappedStatement.getSqlCommandType());
        builder.resource(mappedStatement.getResource());
        builder.fetchSize(mappedStatement.getFetchSize());
        builder.statementType(mappedStatement.getStatementType());
        builder.keyGenerator(mappedStatement.getKeyGenerator());
        builder.keyProperty(mappedStatement.getKeyProperty());
        builder.timeout(mappedStatement.getTimeout());
        builder.resultMaps(mappedStatement.getResultMaps());
        builder.resultSetType(mappedStatement.getResultSetType());
        builder.cache(mappedStatement.getCache());
        builder.useCache(mappedStatement.isUseCache());
        builder.parameterMap(mappedStatement.getParameterMap());
        builder.flushCacheRequired(true);
        return builder.build();
    }
 
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }
 
    @Override
    public void setProperties(Properties properties) {
    }
}

单元测试测试下吧,查缓存的日志

2017-04-14 09:00:21.495 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Creating SqlSession with JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3541d281]
2017-04-14 09:00:21.496 [main] [java.sql.Connection] DEBUG ooo Connection Opened
2017-04-14 09:00:21.500 [main] [com.tangdi.jump.bp.service.sqlmap.support.SpringManagedTransaction] DEBUG JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3541d281] will be managed by Spring
2017-04-14 09:00:27.437 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf]
2017-04-14 09:00:27.442 [main] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf] for iBATIS operation
2017-04-14 09:00:37.826 [main] [java.sql.PreparedStatement] DEBUG ==> Executing: SELECT TO_CHAR(MAX(DT),'YYYY-MM-DD') FROM WORK_HOLIDAY WHERE TRASTATUS = '1' 
2017-04-14 09:00:37.826 [main] [java.sql.PreparedStatement] DEBUG ==> Parameters: 
2017-04-14 09:00:37.842 [main] [java.sql.ResultSet] DEBUG <== Columns: 1
2017-04-14 09:00:37.842 [main] [java.sql.ResultSet] DEBUG <== Row: 2017-04-05
2017-04-14 09:00:37.846 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf]
aa:2017-04-05
2017-04-14 09:00:59.856 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf] from current transaction
2017-04-14 09:00:59.856 [main] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf] for iBATIS operation
2017-04-14 09:00:59.857 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf]
bb:2017-04-05
2017-04-14 09:00:59.857 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf]
2017-04-14 09:00:59.858 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53372fcf]

加入插件,FlushCache后的日志

2017-04-14 09:51:04.864 [main] [java.sql.Connection] DEBUG ooo Connection Opened
2017-04-14 09:51:04.867 [main] [com.tangdi.jump.bp.service.sqlmap.support.SpringManagedTransaction] DEBUG JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@7722306c] will be managed by Spring
2017-04-14 09:51:04.879 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21]
2017-04-14 09:51:04.880 [main] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21] for iBATIS operation
2017-04-14 09:51:07.890 [main] [java.sql.PreparedStatement] DEBUG ==> Executing: SELECT TO_CHAR(MAX(DT),'YYYY-MM-DD') FROM WORK_HOLIDAY WHERE TRASTATUS = '1' 
2017-04-14 09:51:07.890 [main] [java.sql.PreparedStatement] DEBUG ==> Parameters: 
2017-04-14 09:51:07.905 [main] [java.sql.ResultSet] DEBUG <== Columns: 1
2017-04-14 09:51:07.905 [main] [java.sql.ResultSet] DEBUG <== Row: 2017-04-14
2017-04-14 09:51:07.909 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21]
aa:2017-04-14
2017-04-14 09:51:09.837 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21] from current transaction
2017-04-14 09:51:09.838 [main] [com.tangdi.jump.bp.service.sqlmap.impl.SqlMapImpl] DEBUG Opened SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21] for iBATIS operation
2017-04-14 09:51:09.839 [main] [java.sql.PreparedStatement] DEBUG ==> Executing: SELECT TO_CHAR(MAX(DT),'YYYY-MM-DD') FROM WORK_HOLIDAY WHERE TRASTATUS = '1' 
2017-04-14 09:51:09.840 [main] [java.sql.PreparedStatement] DEBUG ==> Parameters: 
2017-04-14 09:51:09.844 [main] [java.sql.ResultSet] DEBUG <== Columns: 1
2017-04-14 09:51:09.844 [main] [java.sql.ResultSet] DEBUG <== Row: 2017-04-14
2017-04-14 09:51:09.845 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21]
bb:2017-04-14
2017-04-14 09:51:09.846 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21]
2017-04-14 09:51:09.848 [main] [com.tangdi.jump.bp.service.sqlmap.support.SqlSessionUtils] DEBUG Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1011dc21]

ok,大功告成,bug完美解决,所以sql查询都必须查询数据库了

总结

吐槽下mybatis的设计问题,ORM好好做数据库的事情,关于缓存的事情不要做,交给redis好了,功能做就做了,但是默认开启就不对了!!! 不管是什么开源项目,都需在保证正确性的下再考虑提示性能.在提示性能有可能引入数据错误的功能应默认关闭!!!!

### 回答1: 设计一个基于 JavaWeb 的线上点餐系统需要考虑以下几个方面: 1. 用户界面设计:需要设计一个易用、直观、美观的用户界面,让用户可以轻松浏览菜单、点餐、结账等操作。 2. 数据库设计:需要设计数据库模型,用于存储菜单信息、用户信息、订单信息等数据。需要考虑到数据库的安全性和可扩展性。 3. 后端服务设计:需要设计后端服务,实现用户注册、登录、点餐、下单、支付等功能。后端服务需要考虑到系统的可靠性和安全性,可以采用 Spring、SpringMVC、MyBatis 等框架来实现。 4. 前端交互设计:需要设计前端页面,实现用户与系统的交互,可以采用 HTML、CSS、JavaScript 等技术来实现。 5. 系统架构设计:需要设计系统架构,包括系统的分层结构、模块划分、系统的部署方式等。 6. 安全性设计:需要考虑系统的安全性,包括用户数据的安全存储、交互数据的加密传输、用户身份验证等方面。 7. 性能优化设计:需要考虑系统的性能优化,包括数据的缓存、页面的静态化、数据库的优化等方面。 以上是设计基于 JavaWeb 的线上点餐系统需要考虑的几个方面,具体实现还需要根据具体的业务需求进行设计和开发。 ### 回答2: 设计一个基于JavaWeb的线上点餐系统,主要包括以下几个步骤: 1. 需求分析:确定系统的功能需求,包括用户注册登录、浏览菜单、下单支付、订单管理等基本功能。 2. 数据库设计:根据需求设计数据库表结构,包括用户表、菜品表、订单表等。使用MySQL等关系型数据库存储数据。 3. 后台开发:使用Java编写后台代码,包括处理用户请求、数据操作、业务逻辑等。使用Spring MVC等框架实现请求的解析与分发。 4. 前端开发:使用HTML、CSS、JavaScript等技术开发前端页面,包括用户注册登录界面、菜品展示界面、购物车界面等。 5. 集成支付接口:选择合适的支付接口集成,实现用户支付功能。 6. 流程优化:不断优化系统流程,提高用户体验。例如,可引入搜索功能、添加菜品分类、推荐菜品等。 7. 安全防护:加强系统的安全性,对用户的密码进行加密处理,确保用户信息的安全性。 8. 性能优化:对系统进行性能优化,减少响应时间,提高系统的并发能力。 9. 测试与部署:进行系统功能测试,修复可能存在的bug,并进行系统的部署与上线。 10. 维护与升级:定期检查系统运行情况,修复可能存在的问题,随时根据需求进行系统的升级与扩展。 通过以上步骤,一个基于JavaWeb的线上点餐系统就可以进行设计和开发。 ### 回答3: 设计一个基于JavaWeb的线上点餐系统需要考虑以下几个方面: 1. 数据库设计:需要设计用于存储菜品信息、订单信息、用户信息等的数据库。可以使用MySQL等数据库管理系统来存储数据。 2. 用户注册与登录:设计用户注册与登录功能,用户可以通过注册账户来登录系统,以便进行点餐和查看订单等操作。 3. 菜品展示与搜索:实现菜品展示页面,展示各个菜品的名称、价格、图片等信息,并提供搜索功能,方便用户根据关键词查找菜品。 4. 购物车功能:设计购物车功能,用户可以将想要点餐的菜品添加到购物车中,并在购物车中查看已选择的菜品和总价,还可以对菜品进行数量的增减操作。 5. 订单生成与支付:用户在购物车确认订单后,系统生成订单,并提供选择支付方式的功能。可以使用第三方支付接口(如支付宝、微信支付)来实现支付功能。 6. 订单管理:设计管理员端界面,管理员可以查看所有订单的详细信息,并对订单进行处理,如确认订单、取消订单等操作。 7. 用户评价与反馈:用户可以对点餐的菜品进行评价,并提供反馈意见,系统可以展示用户的评价和反馈信息。 8. 安全性设计:考虑用户信息的安全性,使用合适的加密算法对用户密码进行加密存储,并使用用户名和密码进行用户身份验证。 以上是基于JavaWeb的线上点餐系统的设计要点,当然在实际开发中还需要进行更加详细的设计和实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值