1 如在MyBatis/Ibatis中#和KaTeX parse error: Expected 'EOF', got '#' at position 5: 的区别?#̲方式能够很大程度防止sql注入…方式无法防止Sql注入。所以,老司机 对新手说,最好用#。简单的说#{}是经过预编译的,是安全的,而
解决一些实际问题。
如在执行sql语句时你有时并不希望让变量进行处理,而是直接赋值执行,这时就要用到(${a})了,在使用时还要这样赋值 @Param(value=“a”) String a。
如日期问题:可能会遇到日期格式的时间段问题,当数据库的时间为DATE类型时,MyBatis的jdbcType应该使用DATE,jdbcType=DATE,而不是使用jdbcType=TIMESTAMP。
如在使用resultMap的时候,要把ID写在第一行,否则的话,就会报错。
2 又如最近在做的项目,遇到myBatis的大坑,Mybatis一直报异常Java.lang.ArrayIndexOutOfBoundsException,于是开始代码查错,代码中有存储过程,然后开发使用ROOT用户执行SQL跑出来的数据结果集是正常的,在测试环境程序运行也正常,但是在正式环境就其他用户不行,最后发现是因为数据库没有给该用户授权出了问题。
3 ,后来经大神指点,sql语句查询出来的这个字段名必须和dto的参数名一致,改成这样就通过了。解决方案:,通过来映射字段名和实体类属性名的一一对应关系,这种方式是使用MyBatis提供的解决方式来解决字段名和属性名的映射关系的!
4 数据库表使用了联合主键,逆向生成的时候生成了两个实体类,看起来别扭,但还是可以用。后来就先取消主键,生成完后再将主键加上。还有就是,tinyint本来以为用来表示比较小的整数,结果生成了布尔型的属性。后来就表示是和否才用tinyint了。逆向生成的sql语句绝对不能人为改动,否则再次生成的时候会重复生成。但是,尽管踩过坑,我还是觉得mybatis超级好用,比hibernate好多了。虽然hibernate我只试过一点之后就完全转向了mybatis了。
5 sum()和count()使用场景不对导致出错。
count()、count(1)、count(0)就是指绝对的行数,哪怕某行所有字段全部为null也会计算在内。count(1)和count()相比,innodb来说count(星)效率低。
如果count(列名)查询出来的结果就是查出列名中不为null的行数
sum(列名)对指定列名进行求和?
MyBatis把int类型的0处理成空串’’和mysql处理空串’’为0的问题,在Mybatis的Mapper中整数类型条件该如何判断?
当数据库字段类型是整数,如果参数变量为空字符串或者NULL,Mybatis会自动将参数赋值0,所以如果要判断整数参数的多种状态在传递数值到Mapper之前就要判断是否为空字符串和NULL并将相应的状态数值赋值给该参数,否则参数值等于空字符串、NULL和0得到的结果是一样的。一般情况下,涉及到int类型的操作的时候,在Service中会统一把数字类型先变成字符串类型,然后再传递到Mapper中操作。
6 时间戳的使用?
在创建新记录的时候把这个字段设置为当前时间,但以后修改时,不再刷新它「可以给createtime使用这个」:TIMESTAMP DEFAULT CURRENT_TIMESTAMP。
在创建新记录和修改现有记录的时候都对这个数据列刷新「可以给update使用这个」:
TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP。
在使用resultMap的时候,要把ID写在第一行,否则的话,就会报错。
7 XML转义字符,如果直接写就会报错,需要用左边一列的转义字符。
< < 小于号 > > 大于号
& & 和
’ ’ 单引号
" " 双引号**
8 前几天在项目中碰到,来说下吧,大神可绕道,在使用selectOne查询个数时。
如果你写了resultType为Integer,然后在业务代码中很自然的用一个变量int去接当前这个方法的返回,如果按照你传入的条件在数据库中没有找到相关的值,此时selectOne方法的返回值会是一个null,当你使用Java的自动拆箱机制的时候会报出一个无情的NPE。
原因:Java在自动拆箱的时候会调用Integer类中的intValue方法,如果当前对象为null,则抛出NPE。
因此,在接受的时候要判空,否则可能异常
9 1、多参数的使用
MyBatis的查询或者更新中,如果需要多个参数有如下几种办法:
对象映射,建立一个Java对象,并作为接口的参数,对象的属性可以直接使用#{属性名}的方式访问;
Map, 参数为一个Map, key对于属性名,value对于参数值,这个方法就是传参数是需要建立一个Map的临时对象
@param参数注解,在接口方法参数前加入参数名称注解,这样就可以直接在Mapper中通过参数名访问
通过序号访问,第一个参数#{0}或#{param1}, 第二个参数#{1}, #{param2}
MyBatis中时间字段的使用–返回
时间字段的返回目前笔者采用放回字符串的方式:
date_format(update_time, ‘%Y-%c-%d %H:%i:%s’) updatetime
采用MySQL的时间格式化方法。
或者放回Timestamp类型的数据,要求放回对象属性参数为Timestamp.
MyBatis中时间字段的使用–参数
如果需要查询一段时间范围的数据时,可以通过以下动态SQL的方式查询数据:
and lbr.update_time > #{startTime}
and lbr.update_time < #{endTime, javaType=Date, jdbcType=TIMESTAMP}
对于的接口方法名称如下:
… Date startTime, Date endTime…
我想这个方法会比通过格式转换的效率要高一些。
MyBatis中时间字段的使用–写入。
写入可是直接写入Timestamp的数据,需要描述一些写入的jdbcType,如下:{installTime, jdbcType=TIMESTAMP}。
**
9 缺点:
sql工作量很大,尤其是字段多、关联表多时,更是如此。
sql依赖于数据库,导致数据库移植性差。
由于xml里标签id必须唯一,导致DAO中方法不支持方法重载。
字段映射标签和对象关系映射标签仅仅是对映射关系的描述,具体实现仍然依赖于sql。(比如配置了一对多Collection标签,如果sql里没有join子表或查询子表的话,查询后返回的对象是不具备对象关系的,即Collection的对象为null)
DAO层过于简单,对象组装的工作量较大。
不支持级联更新、级联删除。
编写动态sql时,不方便调试,尤其逻辑复杂时。
10 提供的写动态sql的xml标签功能简单(连struts都比不上),编写动态sql仍然受限,且可读性低。
若不查询主键字段,容易造成查询出的对象有“覆盖”现象。
参数的数据类型支持不完善。(如参数为Date类型时,容易报没有get、set方法,需在参数上加@param)
多参数时,使用不方便,功能不够强大。(目前支持的方法有map、对象、注解@param以及默认采用012索引位的方式)
缓存使用不当,容易产生脏数据。
几点技巧总结
1、查询很多字段时可以提出来再引入到sql语句。
提取:
id, type, shopCouId, Path, fromDate, toDate, insDate, insUserId, updDate, updUserId, delFlg
引入:
select
from adinfo
where id = #{id,jdbcType=INTEGER}
2、缓存使用
在增删查改时,可以使用缓存属性控制数据缓存。
3、可以判断传进来的参数,再进行操作
and langCd = #{langCd,jdbcType=VARCHAR}
4、可以在sql语句中直接进行加减乘除计算,模糊查询时,需要注意使用方式。
SELECT sum(b.netCnt) + #{netCnt,jdbcType=INTEGER}
FROM collectcnt b
WHERE b.shopId = #{shopId,jdbcType=INTEGER}
AND b.delflg = ‘0’
newCnt = newCnt + 1,
netCnt = netCnt +1,
sumCnt = sumCnt + 1,
AND o.oTime LIKE CONCAT(’%’,#{sdate},’%’)
5、MyBatis把int类型的0处理成空串’’和mysql处理空串’’为0的问题。
当数据库字段类型是整数,如果参数变量为空字符串或者NULL,Mybatis会自动将参数赋值0,所以如果要判断整数参数的多种状态在传递数值到Mapper之前就要判断是否为空字符串和NULL并将相应的状态数值赋值给该参数,否则参数值等于空字符串、NULL和0得到的结果是一样的。
一般情况下,涉及到int类型的操作的时候,在Service中会统一把数字类型先变成字符串类型,然后再传递到Mapper中操作。
在我看来,虽然它有很多臭毛病,但它给我一种傻壮傻壮的感觉,一切都由我来操作,所以我钟情于它。**