【MyBatis】| MyBatis使用⼩技巧

目录

一:MyBatis使用⼩技巧

1. #{}和${}

2. typeAliases

3. mappers

4. IDEA配置⽂件模板

5. 插⼊数据时获取⾃动⽣成的主键


一:MyBatis使用⼩技巧

1. #{}和${}

#{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防⽌sql注⼊,⽐较常⽤!

${}:先进⾏sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注⼊现象。只有在需要进⾏sql语句关键字拼接的情况下才会⽤到!

(1)定义接口CarMapper ,面向接口编程

package com.bjpowernode.mybatis.mapper;

import com.bjpowernode.mybatis.pojo.Car;

import java.util.*;

public interface CarMapper {
    // 根据汽车类型查询
    List<Car>  selectByCarType(String carType);
}

(2)在CarMapper.xml文件中编写sql语句

注意:namespace是接口CarMapper的完整类名,id是接口对应的方法名!

<?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.bjpowernode.mybatis.mapper.CarMapper">
    <select id="selectByCarType" resultType="com.bjpowernode.mybatis.pojo.Car">
      select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from t_car
        where car_type = #{carType}
    </select>
</mapper>

(3)编写测试类,看执行结果对比

package com.bjpowernode.mybatis.test;

import com.bjpowernode.mybatis.mapper.CarMapper;
import com.bjpowernode.mybatis.pojo.Car;
import com.bjpowernode.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class CarMapperTest {
    @Test
    public void testSelectByCarType(){
        SqlSession sqlSession = SqlSessionUtils.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectByCarType("燃油车");
        for (Car car :cars){
            // 会调toString方法
            System.out.println(car);
        }
        sqlSession.close();
    }
}

①使用#{}执行结果,能正常执行结果

特点:先执行SQL语句的编译,然后给SQL语句的占位符问号?传值

②使用${}执行结果,会抛出异常,直接拼接字符串但是没有引号

特点:先执行SQL语句的拼接,然后再对SQL语句进行编译

(4)#{}和${}的选择

注:如果需要SQL语句的关键字放到SQL语句中,只能使用${},因为#{}是以值的形式放到SQL语句当中;例如:升序或者降序排需要传asc或者desc,此时要把这个关键字传进去,就需要${}

①接口类中的方法

package com.bjpowernode.mybatis.mapper;
import com.bjpowernode.mybatis.pojo.Car;
import java.util.*;

public interface CarMapper {
    // 根据汽车类型查询
    List<Car>  selectByCarType(String carType);

    // 查询所有的汽车信息,然后通过asc升序,desc降序
    List<Car> selectByAscOrDesc(String ascOrDesc);
}

②编写sql语句,根据传参按照produce_time升序或者降序

<?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.bjpowernode.mybatis.mapper.CarMapper">
    <select id="selectByCarType" resultType="com.bjpowernode.mybatis.pojo.Car">
      select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from t_car
        where car_type = #{carType}
    </select>

    <select id="selectByAscOrDesc" resultType="com.bjpowernode.mybatis.pojo.Car">
        select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from
            t_car
        order by
            produce_time #{ascOrDesc}
    </select>
</mapper>


③编写测试程序

package com.bjpowernode.mybatis.test;

import com.bjpowernode.mybatis.mapper.CarMapper;
import com.bjpowernode.mybatis.pojo.Car;
import com.bjpowernode.mybatis.utils.SqlSessionUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class CarMapperTest {
    @Test
    public void selectByAscOrDesc(){
        SqlSession sqlSession = SqlSessionUtils.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectByAscOrDesc("asc");
        for (Car car :cars){
            // 会调toString方法
            System.out.println(car);
        }
        sqlSession.close();
    }
}

使用#{},先编译在传值,传的是一个字符串,会有引号,明显不符合语法!

 使用${},先把关键字拼串上去,在进行编译,符合语法规则!

(5) 使用${}完成表名拼接

注:这里需要查询新的表名,所以需要编写新的PoJo类Log、新建配置文件LogMapper.xml、新建一个接口LogInterface、新建测试类LogMapperTest类进行测试、在核心配置文件mybatis-config.xml当中引入LogMapper.xml

①现实业务当中,可能会存在分表存储数据的情况,因为一张表存储数据的话,数据量太大,查询效率比较低。
②可以将这些数据有规律的分表存储,这样扫描的数据量变少了,在查询的时候效率就比较高。例如日志表:专门存储日志信息的,可以每天生成一个新表,每张表以当天日期作为名称,例如:t_log_20220901、t_log_20220902....
③假如想知道某一天的日志信息,假设今天是20230103,那么直接把日期传进去,完成“t_log_日期表”的拼接。

<?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.powernode.mybatis.mapper.LogMapper">

    <select id="selectAllByTable" resultType="com.bjpowernode.mybatis.pojo.Log">
        <!--select * from t_log_#{date}-->
        select * from t_log_${date}
    </select>

</mapper>

(6)使用${}完成批量删除

注:批量删除对应的sql语句有两种写法

第一种:使用or的形式,delete from t_user where id = 1 or id = 2 or id = 3;

第二种:使用in的形式,delete from t_user where id in(1, 2, 3);

①定义的方法中参数实际上是一个String类型的字符串,我们传参的时候,也是一个字符串传过去,例如:mapper.deleteBatch("1,2,3")的形式。

②关键是我们先拼串再编译,还是先编译在传值;前者是字符串的完美拼接,后者是直接把一个字符串传过去,会带有引号!

<delete id="deleteBatch">
     delete from t_car where id in(${ids})
</delete>

(7)使用${}完成模糊查询

需求:根据汽车品牌进行模糊查询
例如:select * from t_car where brand like '%奔驰%';

<select id="selectByBrandLike" resultType="CAR">
        select
            id,
            car_num as carNum,
            brand,
            guide_price as guidePrice,
            produce_time as produceTime,
            car_type as carType
        from
            t_car
        where
            <!--brand like '%#{brand}%'-->
            brand like '%${brand}%'
            brand like concat('%',#{brand},'%')
            brand like concat('%','${brand}','%')
            brand like "%"#{brand}"%"
</select>

如果使用"%#{brand}%",最终#{}底层肯定是转化为?,但是比较尴尬的是放到双引号或者单引号"?"的?是无法识别的,所以无法进行传值!

①解决方法1:使用"%${brand}%",会先进行拼串,然后在编译!

②解决方法2:concat函数,这个是mysql数据库当中的一个函数,专门进行字符串拼接,concat('%',#{brand},'%');这里也可以使用${band},外面加一个单引号,比较鸡肋,
concat('%','${brand}','%')。

③解决方法3:"%"#{brand}"%",把两个%用引号括起来,就能识别中间的?了,就能正常传值了。

2. typeAliases

使用 typeAliases标签完成别名机制!

(1)我们打开CarMapper.xml文件,发现resultType标签的全限定名称很长,包括我们以后写其它类型的查询语句,都要写这个带包的类名;所以就使用别名机制先定义别名。

 <select id="selectByCarLike" resultType="com.bjpowernode.mybatis.pojo.Car">
 </select>

(2)第一种:在核心配置文件mybatis-config.xml文件中使用typeAliases标签下的子标签typeAlias标签起别名。

注:namespace标签必须写全限定名称,是不能起别名的!

①type属性:指定给那个类型起别名

②alias:指定别名

    <typeAliases>
        <typeAlias type="com.bjpowernode.mybatis.pojo.Car" alias="car" />
    </typeAliases>

③ 这样就能在CarMapper.xml文件中运用别名了,并且不区分大小写!

 <select id="selectByCarLike" resultType="car">
 </select>

④实际上alias属性是可以省略的,有默认的别名,别名是类的简名;例如:com.bjpowernode.mybatis.pojo.Car对应的就是Car、car、cAr等等,不区分大小写。

(3)第二种:在核心配置文件mybatis-config.xml文件中使用typeAliases标签下的子标签package指定包名即可。(常用)

我们使用package标签指定一个包名,那么这个包下所有的类全部自动起别名,别名就是类简名,不区分大小写

    <typeAliases>
        <package name="com.bjpowernode.mybatis.pojo" />
    </typeAliases>

 (4)小总结

所有别名不区分大小写;namespace不能使用别名机制!

    <typeAliases>
        <!--别名自己指定的-->
        <typeAlias type="com.powernode.mybatis.pojo.Car" alias="aaa"/>
        <typeAlias type="com.powernode.mybatis.pojo.Log" alias="bbb"/>

        <!--采用默认的别名机制-->
        <typeAlias type="com.powernode.mybatis.pojo.Car"/>
        <typeAlias type="com.powernode.mybatis.pojo.Log"/>

        <!--包下所有的类自动起别名。使用简名作为别名。-->
        <package name="com.powernode.mybatis.pojo"/>
    </typeAliases>

3. mappers

(1)mapper标签的属性可以有三个:

①resource:这种方式是从类的根路径下开始查找资源;采用这种方式,配置文件需要放到类路径当中才行。
②url:这种方式是一种绝对路径的方式,这种方式不要求配置文件必须放到类路径当中,哪里都行,只要提供一个绝对路径就行;这种方式使用极少,因为移植性太差。
③class:这个位置提供的是mapper接口的全限定接口名,必须带有包名的!
例如:<mapper class="com.powernode.mybatis.mapper.CarMapper"/>,

class指定的是:com.powernode.mybatis.mapper.CarMapper,那么mybatis框架会自动去com/powernode/mybatis/mapper目录下查找CarMapper.xml文件

注意:也就是说,如果采用这种方式,必须保证CarMapper.xml文件和CarMapper接口必须在同一个目录下,并且名字一致。如:CarMapper接口-> CarMapper.xml。

解释:所谓的同一个目录,是在resource目录下创建包名,并且这个包名与java下的CarMapper接口包名必须一致,然后把配置文件CarMapper.xml扔到包名里;实际上java和resource都是根目录,只不过两种展现形式!

解释:在resource下创建包,实际上是创建目录,因为只有在java下创建包才是"点"的形式,例如:com.bjpowernode就表示com目录下的bjpowernode目录;对于resource下创建包就是直接创建目录,例如:com/bjpowernode也表示com目录下的bjpowernode目录,如果采用com.bjpowernode就表示一个名为com.bjpowernode的目录。

 <mappers>
    <mapper resource="CarMapper.xml"/> 要求类的根路径下必须有:CarMapper.xml
    <mapper url="file:///d:/CarMapper.xml"/> 要求在d:/下有CarMapper.xml文件
    <mapper class="com.powernode.mybatis.mapper.CarMapper"/> 全限定接口名,带有包名
 </mappers>

(2)假如有很多个接口名,要写很多个全限定接口名也很麻烦;实际上在mappers标签下还有一个package属性,用来指定包名,这种方式在开发中是比较常用的

前提:XML文件必须和接口放在一起,并且名字一致!

解释:指定报名,实际上就是指定这个路径,在这个路径下查找配置文件。

<mappers>
    <package name="com.bjpowernode.mybatis.mapper" />
</mappers>

4. IDEA配置⽂件模板

mybatis-config.xml和SqlMapper.xml⽂件可以在IDEA中提前创建好模板,以后通过模板创建配置⽂件

(1)准备好的mybatis-config.xml核心配置文件的模板

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
    <properties resource=""/>
    <typeAliases>
        <package name=""/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name=""/>
    </mappers>
</configuration>

(2)准备好的SqlMapper.xml配置文件的模板

<?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="">
</mapper>

(3)步骤:File--->Settings--->Editor--->File and Code Templates

(4)使用:以后直接alt+insert就能找到这个模板

 (5)选定这个模板后,就会让你输出文件的名字,例如:mybatis-config 

(6)点击ok,就会自动生成我们自定义模板的核心配置文件mybatis-config.xml

5. 插⼊数据时获取⾃动⽣成的主键

(1)前面用的主键一直是自动生成的,所以我们并不知道主键是多少,要是下面这种业务,⼀个⽤户有多个⻆⾊,一对多,两张表,多的表加外键

 (2)插⼊⼀条新的记录之后,⾃动⽣成了主键,⽽这个主键需要在其他表中使⽤时;插⼊⼀个⽤户数据的同时需要给该⽤户分配⻆⾊:需要将⽣成的⽤户的id插⼊到⻆⾊表的user_id字段 上。

①第⼀种⽅式:可以先插⼊⽤户数据,再写⼀条查询语句获取id,然后再插⼊user_id字段。【⽐较麻烦】

②第⼆种⽅式:mybatis提供了⼀种⽅式更加便捷。

(3)主要是在插入数据时,使用两个属性

useGeneratedKeys="true" 表示使用自动生成的主键值。
keyProperty="id" 指定主键值赋值给对象的哪个属性,就表示将主键值赋值给Car对象的id属性。

<insert id="insertCarUseGeneratedKeys" useGeneratedKeys="true" keyProperty="id">
        insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})
</insert>

(4)测试结果

①如果不加上这两个参数,打印结果主键显示null

 ②如果加上这两个参数,打印结果就会显示自动生成的主键

猜你喜欢

转载自blog.csdn.net/m0_61933976/article/details/128531269