org.springframework.jdbc.BadSqlGrammarException未找到表,但是实际存在

maven配置的项目环境框架:spring mvc + mybatis + sap iq数据库
在后台管理界面有用户和组织关系维护的界面,但是进行组织关系维护操作的时候经常会报错,提示user表找不到,但其实是存在的,而且刷新以后就又可以正常显示了(虽然有时候要多刷新很多次)
首先是报错信息(复制黏贴会比较乱,就截了个图,大家将就看下):

clipboard.png

然后是mybatis配置


    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans  
                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
                            http://www.springframework.org/schema/context  
                            http://www.springframework.org/schema/context/spring-context-3.1.xsd  
                            http://www.springframework.org/schema/mvc  
                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
                            
        <!-- 自动扫描 -->
        <context:component-scan base-package="com.shanshan.bo" />
        <!-- 引入配置文件 -->
        <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:jdbc.properties" />
        </bean>
        
        <!--dataSource管理-->
        <bean id="dynamicDataSource" class="com.shanshan.bo.utils.DynamicDataSource" >
            <property name="targetDataSources">
                <map key-type="java.lang.String">
                    <!--通过不同的key决定用哪个dataSource-->
                    <entry value-ref="mdataDataSource" key="mdataDataSource"></entry>
                    <entry value-ref="devDataSource" key="devDataSource"></entry>
                </map>
            </property>
            <!--设置默认的dataSource-->
            <property name="defaultTargetDataSource" ref="mdataDataSource">
            </property>
        </bean>
        
        <!--多个数据源dataSource-->
        <bean id="mdataDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${iq.mdata.driver}" />
            <property name="url" value="${iq.mdata.url}" />
            <property name="username" value="${iq.mdata.username}" />
            <property name="password" value="${iq.mdata.password}" />
            <!-- 初始化连接大小 -->
            <property name="initialSize" value="${initialSize}"></property>
            <!-- 连接池最大数量 -->
            <property name="maxActive" value="${maxActive}"></property>
            <!-- 连接池最大空闲 -->
            <property name="maxIdle" value="${maxIdle}"></property>
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${minIdle}"></property>
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${maxWait}"></property>
        </bean>
        
        <bean id="devDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${iq.dev.driver}" />
            <property name="url" value="${iq.dev.url}" />
            <property name="username" value="${iq.dev.username}" />
            <property name="password" value="${iq.dev.password}" />
            <!-- 初始化连接大小 -->
            <property name="initialSize" value="${initialSize}"></property>
            <!-- 连接池最大数量 -->
            <property name="maxActive" value="${maxActive}"></property>
            <!-- 连接池最大空闲 -->
            <property name="maxIdle" value="${maxIdle}"></property>
            <!-- 连接池最小空闲 -->
            <property name="minIdle" value="${minIdle}"></property>
            <!-- 获取连接最大等待时间 -->
            <property name="maxWait" value="${maxWait}"></property>
        </bean>
        
        <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dynamicDataSource" />
            <!-- mybatis的配置文件 -->
            <!-- <property name="configLocation" value="/WEB-INF/mybatis/mybatis-config.xml"></property> -->
            <!-- 自动扫描mapping.xml文件 -->
            <property name="mapperLocations" value="classpath:com/shanshan/bo/mapping/*.xml"></property>
        </bean>
        
        <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.shanshan.bo.mapper" />
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        </bean>
    
        <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dynamicDataSource" />
        </bean>
        
    </beans>

报错信息中提到的SsFundDimPortaluserMapper.xml文件内容


    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.shanshan.bo.mapper.SsFundDimPortaluserMapper" >
      <resultMap id="UserResultMap" type="com.shanshan.bo.po.SsFundDimPortaluser" >
        <result column="USER_ID" property="userId" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="USER_CODE" property="userCode" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="USER_NAME" property="userName" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="USER_PASSWORD" property="userPassword" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="BO_USER" property="boUser" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="BO_PASSWORD" property="boPassword" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="NC_USER" property="ncUser" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="DEFAULT_ORG" property="defaultOrg" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="ISADMIN" property="isAdmin" jdbcType="VARCHAR" javaType="java.lang.String" />
        <result column="USER_GROUP" property="userGroup" jdbcType="VARCHAR" javaType="java.lang.String" />
      </resultMap>
      
      <sql id="columns">
          USER_CODE, USER_NAME, USER_PASSWORD, BO_USER, BO_PASSWORD, NC_USER, DEFAULT_ORG, ISADMIN, USER_GROUP
      </sql>
      
      <insert id="insert" parameterType="com.shanshan.bo.po.SsFundDimPortaluser" >
        insert into SS_FUND_DIM_PORTALUSER (USER_ID, USER_CODE, USER_NAME, USER_PASSWORD, 
          BO_USER, BO_PASSWORD, NC_USER, DEFAULT_ORG, ISADMIN, USER_GROUP)
        values (#{userId,jdbcType=VARCHAR}, #{userCode,jdbcType=VARCHAR}, #{userName,jdbcType=VARCHAR}, 
          #{userPassword,jdbcType=VARCHAR}, #{boUser,jdbcType=VARCHAR}, #{boPassword,jdbcType=VARCHAR}, 
          #{ncUser,jdbcType=VARCHAR}, #{defaultOrg,jdbcType=VARCHAR}, #{isAdmin,jdbcType=VARCHAR}, #{userGroup,jdbcType=VARCHAR})
      </insert>
      
      <insert id="insertSelective" parameterType="com.shanshan.bo.po.SsFundDimPortaluser" >
        insert into SS_FUND_DIM_PORTALUSER
        <trim prefix="(" suffix=")" suffixOverrides="," >
          <if test="userId != null" >
            USER_ID,
          </if>
          <if test="userCode != null" >
            USER_CODE,
          </if>
          <if test="userName != null" >
            USER_NAME,
          </if>
          <if test="userPassword != null" >
            USER_PASSWORD,
          </if>
          <if test="boUser != null" >
            BO_USER,
          </if>
          <if test="boPassword != null" >
            BO_PASSWORD,
          </if>
          <if test="ncUser != null" >
            NC_USER,
          </if>
          <if test="defaultOrg != null" >
            DEFAULT_ORG,
          </if>
          <if test="isAdmin != null" >
            ISADMIN,
          </if>
          <if test="userGroup != null" >
            USER_GROUP,
          </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides="," >
          <if test="userId != null" >
            #{userId,jdbcType=VARCHAR},
          </if>
          <if test="userCode != null" >
            #{userCode,jdbcType=VARCHAR},
          </if>
          <if test="userName != null" >
            #{userName,jdbcType=VARCHAR},
          </if>
          <if test="userPassword != null" >
            #{userPassword,jdbcType=VARCHAR},
          </if>
          <if test="boUser != null" >
            #{boUser,jdbcType=VARCHAR},
          </if>
          <if test="boPassword != null" >
            #{boPassword,jdbcType=VARCHAR},
          </if>
          <if test="ncUser != null" >
            #{ncUser,jdbcType=VARCHAR},
          </if>
          <if test="defaultOrg != null" >
            #{defaultOrg,jdbcType=VARCHAR},
          </if>
          <if test="isAdmin != null" >
            #{isAdmin,jdbcType=VARCHAR},
          </if>
          <if test="userGroup != null" >
            #{userGroup,jdbcType=VARCHAR},
          </if>
        </trim>
      </insert>
      
      <select id="selectAll" resultMap="UserResultMap">
          select <include refid="columns"></include> from SS_FUND_DIM_PORTALUSER order by user_code
      </select>
      
      <select id="selectByUserCode" parameterType="String" resultMap="UserResultMap">
          select <include refid="columns"></include> from SS_FUND_DIM_PORTALUSER 
        where USER_CODE = #{userCode,jdbcType=VARCHAR}
      </select>
      
      <update id="updateByUserCode" parameterType="com.shanshan.bo.po.SsFundDimPortaluser">
          update SS_FUND_DIM_PORTALUSER 
          <trim prefix="set" suffixOverrides="," >
          <if test="userName != null" >
            USER_NAME = #{userName,jdbcType=VARCHAR},
          </if>
          <if test="userPassword != null" >
            USER_PASSWORD = #{userPassword,jdbcType=VARCHAR},
          </if>
          <if test="boUser != null" >
            BO_USER = #{boUser,jdbcType=VARCHAR},
          </if>
          <if test="boPassword != null" >
            BO_PASSWORD = #{boPassword,jdbcType=VARCHAR},
          </if>
          <if test="ncUser != null" >
            NC_USER = #{ncUser,jdbcType=VARCHAR},
          </if>
          <if test="defaultOrg != null" >
            DEFAULT_ORG = #{defaultOrg,jdbcType=VARCHAR},
          </if>
          <if test="isAdmin != null" >
            ISADMIN = #{isAdmin,jdbcType=VARCHAR},
          </if>
          <if test="userGroup != null" >
            USER_GROUP = #{userGroup,jdbcType=VARCHAR},
          </if>
        </trim>
        where USER_CODE = #{userCode,jdbcType=VARCHAR}
      </update>
      
      <delete id="deleteByUserCode" parameterType="String">
          delete from SS_FUND_DIM_PORTALUSER where USER_CODE = #{userCode,jdbcType=VARCHAR}
      </delete>
      
    </mapper>

因为我这里涉及到多数据库连接,在mybatis的配置文件中有动态配置的过程,另外还有两个java文件来实现动态分配连接哪个数据库用户。个人猜测是有影响的,因为我一开始只连一个数据库用户的时候基本没有这个报错(可能有,但偶发,而且刷新一下肯定就好了,不像现在刷新好几次都不一定好用),但不能证明

阅读 8.4k
1 个回答

自问自答吧,问题原因我也找到了。
因为使用的是多数据库连接配置,然后我有设置过一个默认连接,如果不是连接默认数据库查询数据,在查询之前会修改连接配置。
比如默认连接A数据库,同时还有B数据库连接存在。当修改连接到B数据库查询数据以后,再去连接A数据库查询数据的时候,我以为是会自动应用默认连接配置,但是实际上还是会应用B数据库的连接配置,此时就会导致查不到表的情况,因此报错。
解决方案是在配置了默认连接的基础上,还在每次查询数据之前,不论是连A还是B,都重新设置一个数据库连接。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题