Mybatis 错误笔记

将自己遇到的一些错误总结一下,方便以后复习回顾。同时也希望能帮助一些人

Mybtais错误

1. org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException
1)There is no getter for property named ‘param’ in ‘class java.lang.String’

parameterType=“string”,并判断了 参数是否为空

<select id="xxxxxx" parameterType="string" resultType="int">
		SELECT 
			COUNT(*) 
		FROM VIEW_USER_INFO T   
		<where>	
			<if test="param!=null">
				T.CORP_ID like #{param}||'%' OR T.CORP_NAME like '%'||#{param}||'%'		
			</if>
		</where>
	</select>

使用<if>等的标签的时候,默认情况下,mybatis默认使用OGNL寻找String的param属性。
解决方案

  • 使用 _parameter 替换参数
  • 使用mybatis默认的对象名:value 替换参数
<select id="xxxxxx" parameterType="string" resultType="int">
		SELECT 
			COUNT(*) 
		FROM VIEW_USER_INFO T   
		<where>	
			<if test="value!=null">
				T.CORP_ID_CUS like #{param}||'%' OR T.CORP_NAME like '%'||#{param}||'%'		
			</if>
		</where>
	</select>

参考文献:parameterType为基本类型时的使用方法

同理,类似的错误 There is no getter for property named 'xxx' in 'class XXXXXX',问题一般如下:

  • 字段名写错了
  • 没有对应的 getter 方法
2) Could not set property ‘xxxx’ of ‘class className’ with value ‘xxxx’

主要原因就是<resultMap id='xx' type="className"><column column="" property="xxx"> property属性名没有写正确,这样就无法在type中指定的类里中找到相应的的settter方法。

2.Cause: java.sql.SQLException: ORA-00911: 无效字符 ; bad SQL grammar []; nested exception is java.sql.SQLException: ORA-00911: 无效字符

; bad SQL grammar []一般是语法错误,检查一下sql是否可以在数据库中正常运行。
但是如果在数据中可以运行的话,检查一下映射文件是否写;
解决方法 : 检查是否在sql语句的末尾有;,在映射文件中不需要写;

此外,一般情况下一条语句对应一个mapper标签。如果在一个标签中执行多条语句时,也会报该错误。
这与底层的sql驱动程序有关详情

3.在数据库中执行sql有值,使用mabatis取出来后却为null
  • 主要的原因就是实体类属性和数据库 字段无法匹配,mybatis找不到对应的映射关系,导致为null。
  • 如果确定列名称或者别名 和 Java实体中属性名一致。那么检查一下列字段是否使用了下划线_。如果是那么Java实体属性需要修改为不带下划线的方式。即 USER_ID(数据库) -> userId(javabean)

原因可能是开启了下划线和驼峰标记映射
<setting name="mapUnderscoreToCamelCase" value="true"/>

4. The content of elements must consist of well-formed character data or markup.

错误的大概意思是 “ 元素内容必须由格式良好的字符数据或者标记组成”,也就是说xml元素中包裹的内容有错误。

网上很多都在说元素本身的错误。比如 < p>aa </p> <122>as</122>.。有以下依据
XML 元素必须遵循以下命名规则:

  • 名称可以含字母、数字以及其他的字符
  • 名称不能以数字或者标点符号开始
  • 名称不能以字符 “xml”(或者 XML、Xml)开始
  • 名称不能包含空格

我的问题并不是元素本身的出的问题,而是元素内容(sql 语句)中出现< 和 >而报出的错误。

  1. 用转义字符把">“和”<"替换掉。

    &lt;     	<   	小于号   
    &gt;     	>   	大于号   
    
    <if test="time!= null ">
        AND  lastLogin &lt;= #{time,jdbcType=DATE}>
    </if>
    
  2. 使用<![CDATA[ ]]>符号进行说明,将此类符号不进行解析

    <if test="time!= null ">
        AND <![CDATA[ lastLogin <= #{time,jdbcType=DATE} ]]>
    </if>
    
5.org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) xxxxxMapper.xxmethod:

一般原因是Mapper interface和xml文件的定义对应不上,需要检查包名,namespace,方法名称等能否对应上。

  1. 检查配置文件中package名称是否和Mapper接口的全限定类型一致
  2. 检查映射文件中mapper的namespace属性是否和Mapper接口的全限定类名一致
  3. 检查Mapper接口中的方法名是否能在映射文件找到对应的id
6. org . apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause : com.mysql.jdbc .MysqlDataTruncation: Data truncation:Incorrect datetime value :’ 10:20:30’

数据库字段和映射文件中配置的字段不匹配。数据库字段‘datetime’,指定的数据类型‘time’。time和datetime 不兼容。
datetime可以兼容timestamp和date类型。

7. org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: The JDBC Type must be specified for output parameter. Parameter: sqlStr

错误原因:调用存储过程时,没有指定输出参数的类型。

<select id="callProcedureHead"  statementType="CALLABLE" resultType="map" parameterType="map">
 	 CALL LOOP_QUESTIONNAIRE_HEAD( #{questionnaireId},#{sqlStr,mode=OUT,jdbcType=VARCHAR}) 
</select>
8.org.springframework.core.NestedIOException: Failed to parse mapping resource: ‘file [xxx.xml]’; nested exception is org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.builder.BuilderException: Error resolving ParameterMode. Cause: java.lang.IllegalArgumentException: No enum constant org.apache.ibatis.mapping.ParameterMode.in

调用存储过程时,IN,OUT必须大写。
同时mode,javaType,jdbcType 必须小写

9. Mapped Statements collection already contains value for ’ com.example.mapper.TestMapper.selectPerson’

在Mybatis映射文件中 namespace.id 必须唯一。当出现上述问题是,说明 namespace (com.example.mapper.TestMapper)下存在多个 相同的Id(selectPerson)。

  • 那么首先检查 映射文件 TestMapper.xml 下是否存在相同的 Id。存在则修改为其他名称即可
  • mapper 映射文件可能被加载多次。找出可能加载 mapper.xml 文件的地方
    • spring-boot 配置文件application.properties 或application.yml 自动装配 mybatis

      	mybatis:
      		mapper-locations:mapper/*
      
    • 加载了 mybatis 配置文件。mybatis-config.xml 配置文件中可以加载 mapper

       <mappers>
           <mapper resource="mybatis/mapper/TestMapper.xml"/>
       </mappers>
      
    • 自定义配置

      mybatis.configuration.mapperLocations=mybatis/mapper/*
      
       SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
       factoryBean.setDataSource(dataSource); //配置数据源
       factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().
       						getResources(mapperLocations));  //加载xml文件
      
10. Parameter ‘__frch_item_0’ not found

在Mybatis 映射文件使用 foreach 元素时可能会抛出该问题。

/*  List<User>  */
<foreach colleaction="users" item="user" >
	#{user.usersId}
</foreach>

我项目中报改错的原因是 属性字段写错了。 实体 User 没有 usersId字段 而是 userId

ORACLE 错误

1. ORA-01013: 用户请求取消当前的操作

这个Oracle报的错误,主要就是请求超时的原因。有可能是当前访问量特别大导致的;也可能是设置的超时间太短;也可能是出现死锁。

我遇到的问题就是死锁,当时在Oracle可视化工具(sql developer)中执行了更新操作但是并没有commit,所以导致事务一直占用表的写锁。从而导致其他的写操作一直等。 如果是这种原因,commit提交就可以了
如果是因为请求时间太短导致的问题

#java解决方法
Statement.setQueryTimeout(0);

#修改配置文件
$ORACLE_HOME/network/admin/sqlnet.ora . 
#添加或修改成:
sqlnet.expire_time = 0
这将关闭oracle的连接状态检测

参考

Mybatis配置文件 控制请求超时时间

<setting name="defaultStatementTimeout" value="60" />
2. Error querying database. Cause: java.sql.SQLException: ORA-01745: 无效的主机/绑定变量名

因为需要按照指定字段排序所以直接在原来的sql中添加Order by #{orderBy} #{order},结果就抛出这个错误。
原因大概如下

  • 结果集中的字段含有对应的数据库产品的关键字,
  • 在xml文件中的SQL语句中,两个填充变量间没有写逗号。
  • 一次性插入大量数据

很明显我的错误的原因时第二个,占位符的方式传递参数是没有逗号将SQL语句中order by #{sortName} #{sortOrder} 改写为<![CDATA[order by ${sortName} ${sortOrder} ]]>问题就解决了!

参考博客

我在网上查找资料的时候其实只提供了前两个出错原因。在实际操作的时候因需求需要要插入1000+的数据(大部分数据已经存在其他的数据表里面),此时就报错了。使用的连接池是DruidDataSource,当程序还停留在解析sql语句的时候(预编译sql还有开始赋值),Sql Connection就自动关闭了。当时也查询了很多资料,感觉最好的解释就是,连接池会在一定时间后回收连接。根据指示修改了配置removeAbandonedTimeout,结果也没有起作用。

后来的解决方案有两种:

  • 分块插入,一次插入500条,这样就没有报错了。虽然没有报错但是速度很慢。
  • 将数据插入逻辑放在数据库端。这样可能减少mybatis的参数解析工作量,同时减少网络的数据传输量。INSERT INTO tableName( id,name,sex,....) SELECT #{id},name,sex FROM (子查询语句 | 表名)。比较推荐这样方式。
3. java.sql.SQLException: ORA-01114: 将块写入文件 201 时出现 IO 错误 (块 # 1015305)

ORA-27069: skgfdisp: 尝试在文件范围外执行 I/O
OSD-04026: 传递的参数无效。 (OS 1015311)
ORA-01114: 将块写入文件 201 时出现 IO 错误 (块 # 1015305)
ORA-27069: skgfdisp: 尝试在文件范围外执行 I/O
OSD-04026: 传递的参数无效。 (OS 1015311)

场景 : 导出大量历史数据到csv文件中的时候,抛出该错误。

错误原因: 数据库临时表空间满了或者坏掉了
解决方案:
查询临时表空间的大小
select creation_time,name, bytes/1024/1024 as “大小(M)” from v$tempfile order by bytes;
在这里插入图片描述
可能就是因为临时空间太小并且不能扩容的原因。

解决办法:

1、查询该用户下的默认临时表空间
select * from database_properties where property_name=‘DEFAULT_TEMP_TABLESPACE’;
2、创建新的临时表空间
create temporary tablespace temp01 tempfile ‘xxxxxxx.DBF’ size 1000M autoextend on;
3、修改默认表空间
alter database default temporary tablespace temp01;

参考博客ORA-01114错误原因及解决方法(临时表空间坏掉、或者满了)

4. ORA-00018 Maximum number of sessions exceeded超出最大会话数

Oracel默认Process的值为150,导致实际的Session值会超过Oracle的设置值(Session的数量是Process*1.1+5),所以会出错。

5. ORA-01791:not a SELECTed expression
select distinct name from DM.USER_BASE order by created_time desc; 

类如上面的sql语句就会报该错误,因为 distinct 和order by一起使用的时候,order by中必须是常量或者select列表中出现的表达式。
有点像group by

select distinct name,created_time  from DM.USER_BASE order by created_time desc; 
ORA-01461:仅能绑定要插入 LONG 列的 LONG 值

错误场景:日志插入错误信息时,没有限定长度,结果e.toString()异常信息特别多。就报的这个错误。

原因: Oracle 中 如果字节类型大于4000个字节时就会被转成Long型。

  1. 可以限定异常信息长度
  2. 修改数据类型
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值