一、localtimestamp - 时间格式字段处理
// sql
created_time timestamp(0) default LOCALTIMESTAMP not null
// java
localtimestamp
default LOCALTIMESTAMP,可以设置默认时间是插入数据的时间
我最初设置了上述这样,然后这样插入值:
<insert id="insert" parameterType="Market">
insert into cs_market_service(id,
...
created_by,
created_time
...)
values (nextval('seq_cs_common'),
...
#{createdBy},
#{createdTime},
...)
<selectKey order="AFTER" keyProperty="id" resultType="Integer">
SELECT currval('seq_cs_common')
</selectKey>
</insert>
然后一直报错:createdTime不允许为null,但是传入了 null 值,因为我这个 java 里没有传这个值。有2种方式可以解决。
1、localtimestamp —— 将上面的 #{createdTime} 改为 下面的localtimestamp即可
<insert id="insert" parameterType="Market">
insert into cs_market_service(id,
...
created_by,
created_time
...)
values (nextval('seq_cs_common'),
...
#{createdBy},
localtimestamp,
...)
<selectKey order="AFTER" keyProperty="id" resultType="Integer">
SELECT currval('seq_cs_common')
</selectKey>
</insert>
2、第2种方案:取消数据库的 not null 限制
利用数据库的 default LOCALTIMESTAMP,可以设置默认时间是插入数据的时间。
然后将上面的 created_time 的设置删掉即可,让数据库去默认填值就行了。推荐这种方式。
二、报错:operator does not exist: integer == integer
今天在 Mybatis 里执行时,控制台报错:operator does not exist: integer == integer,起初不知道什么原因,还以为是传值问题。
后来才发现原来是写法写错了,在 Mybatis 里写了
// 错误写法
ms.status == 0
// 正确写法
ms.status = 0
这是代码里的 == 搞习惯了,马虎导致。
三、如何打开本地 sql 执行的显示
在本地执行时,有时候 sql 报错,如果不打开调试的话,看不到具体 sql 长啥样,不太好调试,那么如何才能打开调试呢?这样在配置文件加入该 Dao 层的调试即可。
logging.level.com.enmox.emcs.market.dao: debug
四、MyBatis 中 ${}和 #{}千万不要乱用
Mybatis 的Mapper.xml语句中parameterType向SQL语句传参有两种方式:#{}和${}
1、#{} 是预编译处理
MyBatis在处理 #{ } 时,它会将sql中的 #{ } 替换为 ?,然后调用 PreparedStatement 的 set 方法来赋值,传入字符串后,会在值两边加上单引号。
如上面的值 “4,44,514”就会变成“ ‘4,44,514’ ”;
2、${} 是字符串替换
在处理字符串替换时,它会将 sql 中的 {} 替换为变量的值,传入的值不会加两边的单引号。
3、注意:使用${ }会导致sql注入,不利于系统的安全性!
SQL注入:就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。常见的有匿名登录(在登录框输入恶意的字符串)、借助异常获取数据库信息等
我们经常使用的是 #{},一般解说是因为这种方式可以防止SQL注入,简单的说 #{} 这种方式SQL语句是经过预编译的,它是把 #{} 中间的参数转义成字符串,举个例子:
select * from student where student_name = #{name}
-- 预编译后,会动态解析成一个参数标记符?:
select * from student where student_name = ?
-- 而使用${}在动态解析时候,会传入参数字符串
select * from student where student_name = 'lyrics'
总结:
#{} 是编译好 sql 语句再取值
${} 是取值后再去编译 SQL 语句
4、具体用例
--#{}方式能够很大程度防止sql注入。
-- $方式无法防止Sql注入。
-- $方式一般用于传入数据库对象,例如传入表名。
-- 一般能用#的就别用$。
select * from ${prefix} ACT_HI_PROCINST where PROC_INST_ID_ = #{processInstanceId}
上面的 ${prefix} 就用来传入表名。