mybatis刚从@Annotation向xml转换时遇到的一些坑

  1. 老碰到少了逗号“,”的情况,导致sql出错,但是这类问题又不容易察觉到,幸好如果有异常堆栈打出的话,这类问题还是比较好发现的。比较麻烦的事是在某厂,当时碰到的这个服务本地无法启动,但是本人初来乍到,一是不熟悉整个系统,找不到启动失败原因在哪儿,而且据说这个问题对于团队老人们都比较难解决,项目又忙,暂时只能通过部署在远程服务器上测试了,二是项目工期压力大,deadline近在眼前,没有时间解决本地启动问题,这类xml又无法远程debug的时候进行热部署,所以每次错一次就得花好久部署一次,极大拖慢研发速度,消耗本猿的耐心,可以说本文极大出生的极大原因是因为这个小小的逗号。可以说这个问题当时除了每次写完在提交的时候细细的查一遍更新的SQL有没有少逗号外,无解。(更新:其实可以通过SqlSessionFactory重新加载mapper.xml文件)

  2. 的使用错误,在组合使用 + 的时候,由于语法不熟,项目又忙,没有时间先学习一下mybatis xml的语法,以为用过注解写个xml还是没问题的,所以这个地方在标签里面一些属性正常更新,一些属性需要if判断来更新的时候碰到的坑,还有一个逗号“,”问题,默认标签是会自动去除末尾逗号的,如下:

<update id="update" >
		update
		user
        <set>
                modify_time = now(),		//set标签里面就不用再写set了,需要判断就加if,不需要就直接这么写即可,标签等同于set,一个sql语句只能写一个,所有更新语句全部写在标签里
                modifier = #{modifier},    //这个地方就算下面没有更新项了,逗号也会默认去掉,不会影响,如果没有这个逗号,下面还有条件生效时,两个赋值语句中间就会缺少逗号
            <if test="name != null">
                name=#{name},
            </if>
            <if test="idCard != null">
                id_card=#{idCard},
            </if>
        </set>
		WHERE
		is_deleted = 0
	</update>
  1. 在写大于小于(>, <,>=,<=)符号时,由于这些符号是特殊字符(很明显系统可能会判断错误为xml的标签开头),在解析xml文件时会被转义,为了不让它们被转义,我们用来包上这部分语句,CDATA 全名:character data,所有 XML 文档中的文本均会被解析器解析,除了 CDATA 区段(CDATA section)中的文本会被解析器忽略。

  2. 在写了mapper.xml后,接口调用依然一直抛异常:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.user.mapper.UserMapper.queryByPage,意思就是queryByPage这个接口找不到咯?但是mapper.xml里其实是有的,最后发现还需要将mapper注册到mybatis-config.xml配置中。

@Mapper
public interface UserMapper {
    List<UserDO> queryByPage(@Param("userQuery") UserQuery query);
}
<?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.user.mapper.UserMapper">
	<select id="queryByPage" resultMap="userDO_resultMap"
            parameterType="com.user.query.UserQuery">
        SELECT *
        FROM global_rule_config
        WHERE is_deleted = 0
        order by id desc
        limit #{userQuery.startPos},#{userQuery.pageSize}
    </select>
</mapper>



<configuration>
	<typeAliases>
        <package name="com.user.dao"/>
    typeAliases>
    <mappers>
    	//这个地方还需要另配,在注解到里面是不需要的,这个地方是不是可以通过自动扫描自动加载呢?
    	<mapper resource="mapper/userMapper.xml"/>
    mappers>
configuration>
  1. 在使用标签的时候,如果传参是单独的参数,可以使用数组作为集合,如果使用的是对象,对象中的某个属性是数组的话将无法解析(体现为无法找到映射的sql,这个问题会因为各种语法错误导致,有问题仔细看日志),需要更改为List。

int queryUsers(@Param("userQuery") UserQuery query);

//如果使用的不是UserQuery对象包装参数,而是参数单独写,则不会有问题
int queryUsers(@Param("userIds") List<Long> userIds);
<!-- 这个地方UserQuery对象中userIds如果是数组将会报错,映射不到对应的sql上 -->
<select id="queryUsers" resultMap="userDO_resultMap" parameterType="com.user.query.UserQuery">
	SELECT * FROM user WHERE is_deleted = 0
        <if test="userQuery.userIds != null and userQuery.userIds.size() > 0">
            and user_id IN
            <foreach item="userId" index="index" collection="userQuery.userIds"  open="(" separator="," close=")">
                #{userId}
            </foreach>
        </if>
</select>
org.mybatis.spring.MyBatisSystemException: null
	at org.apache.ibatis.ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1247)
	at org.apache.ibatis.ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
	at org.apache.ibatis.ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1370)
	at org.apache.ibatis.ognl.ASTMethod.getValueBody(ASTMethod.java:90)
	at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
	at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
	at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:141)
	at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
	at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
	at org.apache.ibatis.ognl.ASTGreater.getValueBody(ASTGreater.java:50)
	at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
	at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
	at org.apache.ibatis.ognl.ASTAnd.getValueBody(ASTAnd.java:61)
	at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
	at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258)
	at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:494)
	at org.apache.ibatis.ognl.Ognl.getValue(Ognl.java:458)
	at org.apache.ibatis.scripting.xmltags.OgnlCache.getValue(OgnlCache.java:44)
	at org.apache.ibatis.scripting.xmltags.ExpressionEvaluator.evaluateBoolean(ExpressionEvaluator.java:32)
	at org.apache.ibatis.scripting.xmltags.IfSqlNode.apply(IfSqlNode.java:34)
	at org.apache.ibatis.scripting.xmltags.MixedSqlNode.apply(MixedSqlNode.java:33)
	at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:41)
	at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:292)
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:81)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:148)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

终其所有,都是因为在开干之前没有好好的研读一下xml的语法,这里后知后觉,并附上一份比较好的xml语法地址:mybatis语法

你可能感兴趣的:(mybatis)