时间格式字段处理(localtimestamp)、报错:operator does not exist: integer == integer、打开本地sql执行显示、MyBatis中${}和#{}使用场景及区别

一、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注入。
-- $方式一般用于传入数据库对象,例如传入表名。
-- 一般能用#的就别用$。
  举个activiti工作流的例子:
select * from ${prefix} ACT_HI_PROCINST where PROC_INST_ID_ = #{processInstanceId}

  上面的 ${prefix} 就用来传入表名。

posted @ 2021-06-03 22:20  古兰精  阅读(699)  评论(0编辑  收藏  举报