mybatis常见用法总结

1、唯一索引自增长

useGeneratedKeys=“true” keyProperty=“id” keyColumn=“id”

<insert useGeneratedKeys="true" keyProperty="id" keyColumn="id">
</insert>

useGeneratedKeys: 告诉Mybatis这个逐主键是否使用数据库的内置规则生成

keyProperty:指定id为主键字段

keyColumn:指定id为数据对应的字段

补充:数据库表需要设置该自增长字段的自增规则

正常使用方法如下:

<!-- 批量插入列表遇到名字重复的就跳过-->
<insert id="insertPerson" paramterType="list" useGeneratedKeys="true" keyProperty="idP" keyColumn="id_p">
    INSERT INTO t_persons (LastName, FirstName, Address, City)
            VALUES 
         <foreach collection="personList" item="item" index="index" separator=",">
            (
	             #{item.lastName}, #{item.firstName}, #{address}, #{city}
            )
        </foreach>
</insert>

useGeneratedKeys的两个易踩的“坑”:

1.1 使用useGeneratedKeys的时候,如果在插入数据的同事又进行更新或跳过插入操作的话,会导致返回数据错位

如下代码:

<!-- 批量插入列表遇到名字重复的就跳过-->
<insert id="batchInsertPerson" parameterType="list" useGeneratedKeys="true" keyProperty="idP" keyColumn="id_p">
    INSERT INTO t_persons (LastName, FirstName, Address, City)
    VALUES
    <foreach collection="personList" item="item" index="index" separator=",">
        (
        #{item.lastName}, #{item.firstName}, #{item.address}, #{item.city}
        )
    </foreach>
    on conflict (LastName, FirstName) DO nothing;
</insert>

有可能的异常如下:

数据库表中已经有个wang five 了,批量插入数据([zhang、three]、[wang、five]、[li、four]),预期如下

id(生成的字段) FirstName  LastName 
2			 zhang	  	three	
null		 wang 		five 
3			 li			four

真实的返回对象如下:

id(生成的字段) FirstName  LastName 
2			 zhang	  	three	
3			 wang 		five 
null		 li			four

1.2 使用useGeneratedKeys批量更新时用多条sql进行拼接

如下错误代码:

<insert id="batchInsertPerson" parameterType="list" useGeneratedKeys="true" keyProperty="idP" keyColumn="id_p">
    <foreach collection="personList" item="item" index="index" separator=";">
	    INSERT INTO t_persons (LastName, FirstName, Address, City)
    	VALUES
        (
        #{item.lastName}, #{item.firstName}, #{item.address}, #{item.city}
        )
    </foreach>
</insert>

如何又更新又插入并且还能返回唯一索引值?

方法也是有的,可以使用, 如下示例,不过这种不支持批量返回

    <insert id="insertUpdatePerson" parameterType="com.dreamkite.pg.entity.Person">
        <selectKey keyProperty='idP' resultType='java.lang.String' order='AFTER'>
            select Id_P from t_persons
            where LastName = #{lastName} and FirstName = #{firstName}
        </selectKey>
        with "temp" as (
            update t_persons set Address = #{address}, City = #{city}
            where LastName = #{lastName} and FirstName = #{firstName}
            returning *
        )
        INSERT INTO t_persons (LastName, FirstName, Address, City)
        select #{lastName}, #{firstName}, #{address}, #{city}
        where (select count (*) from temp) = 0
    </insert>

2、使用<![CDATA[ ]]>减少转义字符的使用

写的sql中有一些特殊的字符的话,在解析xml文件的时候会被转义,但我们不希望他被转义,所以我们要使用<![CDATA[ ]]>来解决

应用场景:如果文本包含了很多的"<“字符 <=和”&"字符——就象程序代码一样,那么最好把他们都放到CDATA部件中

如下:

<select id="getId" parameterType="java.util.HashMap" resultMap="userInfo1">
  <![CDATA[
  SELECT * FROM t_persons  WHERE 1=1  AND  birthDay > #{startTime} AND birthDay <= #{endTime}
  ]]>
  <if test="etidName!=''">
   AND newsEdit=#{etidName}
  </if>
</select>

相反,如果少量包含则可以使用对应的转义符号进行替代,如下

HTML 原始码显示结果
&lt;<
&gt;>
&amp;&
&quot;"
&le;< =
&ge; >=

3、使用对象替代繁杂的入参

当mybatis对应的mapper操作的入参有多个时候,如下:

@Repository
public interface PersonDao {
    void insertPerson(@Param("id") int id, @Param("lastName") String lastName, @Param("firstName") String firstName,
                  @Param("address") String address, @Param("city") String city);
}

以下有两种写法,可以大幅提高代码的可读性,如下:

1、使用一个对象将所有的入参都包起来, dao层代码可以这么写:

@Repository
public interface PersonDao {
    void insert(Person person);   
}
<insert id="insertPerson">
    INSERT INTO t_persons (LastName, FirstName, Address, City)
    select #{lastName}, #{firstName}, #{address}, #{city}
</insert>

2、当一个对象不能把所有的属性都包括起来,那也是可以的,还是用上面做例子

这里记得函数需要添加**@Param**

@Repository
public interface PersonDao {
    void insert(@Param("name")PersonName personName, @Param("addr")PersonAddress personAddress);   
}
<insert id="insertPerson">
    INSERT INTO t_persons (LastName, FirstName, Address, City)
    select #{name.lastName}, #{name.firstName}, #{addr.address}, #{addr.city}
</insert>

4、Java时间数据类型跟数据库如何对应

java数据类型数据库日期说明
java.time.DateDate日职:YYYY-MM-DD
java.time.TimeTime[WITHOUT TIME ZONE]时间:HH-MM-ss
java.time.TimeTIMESTAMP[WITHOUT TIME ZONE]日期时间: YYYY-MM-DD HH-MM-ss
java.time.OffsetDateTimeTIMESTAMP WITHOUT TIME ZONE带时区的日期时间: YYYY-MM-DD HH-MM-ss

补充:在提到时间戳的数据类型时,不得不提到还有一种时间间隔的类型interval, 不过这个在java原生的代码中没有对应的数据类型对应,所以针对这种我一般都是转换成字符串或者long类型

5、在mybatis如何进行字符串拼接

1、使用concat()拼接

<insert id="querySomePerson">
	select * from t_persons where name like concat('%',#{name},'%')
</insert>

2、使用${}代替#{}

<insert id="querySomePerson">
	select * from t_persons where name like '%${name}%'
</insert>

KaTeX parse error: Expected 'EOF', got '#' at position 4: {}跟#̲{}的差别是{}是直接替换的,有存在被黑客攻击的分享,使用该曾经需要做强校验

本博客使用的数据库:postgres

对应的代码也上传到github了, 可戳:https://github.com/junkaitongxue/LearnSpringBoot/tree/main/usePostgres/src/test/java/com/dreamkite/pg/dao/PersonDaoTest.java

(以上为DreamKite本人原创,转载请附上原文链接)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dream_Kite

你的鼓励,是我不断创作的动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值