Mybatis核心知识点整理,面试必备!

相关PDF版资料已同步微信公众号

乐享Coding

欢迎你的关注,二维码在文章底部,获取最全Java学习资料和相关电子书!

Mybatis框架

ORMapping:对象关系映射

关系指关系型数据库的映射

Java到MySQL的映射,开发者可以以面向对象的思想进行开发。

优点
  1. 封装JDBC,减少代码量
  2. SQL写在XML文件里,降低耦合度,便于统一管理和优化,并可重用。
  3. 提供XML标签,支持编写动态SQL语句
  4. 提供映射标签,支持对象与数据库的ORM字段关系映射。
缺点
  1. SQL语句编写工作量较大,尤其是字段多,关联表多时,更是复杂。
  2. SQL语句依赖数据库,不同数据库SQL语句存在细微差异,不能随意更换数据库。

开发方式

  • 原生接口
  • Mapper代理实现自定义接口

初步使用

导入依赖

<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
  • 创建t_account表
CREATE TABLE t_account(
	id INT PRIMARY KEY AUTO_INCREMENT,
	username VARCHAR(11) ,
	pwd VARCHAR(11),
	age INT
)
  • 创建实体类Account进行映射
@Data
public class Account {
    private Integer id;
    private String username;
    private String pwd;
    private Integer age;
}
  • 全局配置核心文件SqlMapperConfig.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>
    <!--配置mybatis运行环境-->
    <environments default="development">
        <environment id="development">
            <!--配置jdbc事务管理-->
            <transactionManager type="JDBC"/>
            <!--配置JDBC数据源连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatisExercise?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="77549252"/>
            </dataSource>
        </environment>
    </environments>
</configuration>
使用原生接口

1.Mybatis框架需要开发者自定义SQL语句,写在Mapper.xml文件中,实际开发中,会为每个实体类创建对应的Mapper.xml,定义管理该对象数据的SQL。

  • namespace通常设置为文件所在包+文件名的形式。
  • insert标签表示执行添加操作
  • select标签表示执行查询操作
  • update标签表示执行更新操作
  • delete标签表示执行删除操作
  • id是实际调用Mybatis方法时需要用到的参数。
  • parameterType是调用对应方法时参数的数据类型
<?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.Long.Mapper.XML.AccountMapper">
<!--    <select id=""></select>-->
<insert id="add" parameterType="com.Long.Entity.Account">
insert into t_account(username,pwd,age) values (#{username},#{pwd},#{age});
</insert>
<!--    <delete id=""></delete>-->
<!--    <update id=""></update>-->
</mapper>

2.AccountMapper.xml注册到全局配置核心文件SqlMapperConfig.xml文件中

<!--注册AccountMapper.xml-->
<mappers>
    <!--这里路径用/-->
    <mapper resource="com/Long/Mapper/XML/AccountMapper.xml"></mapper>
</mappers>

3.pom.xml配置java目录下的xml文件生效,默认只是resource目录下xml文件生效

<!--配置java目录下xml文件生效-->
<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

4.测试

public class testMybatis {
    public static void main(String[] args) {
        //加载Mybatis配置文件
        InputStream InputStream = testMybatis.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
        SqlSession sqlSession = Factory.openSession();
        String statement="com.Long.Mapper.XML.AccountMapper.add";
        Account account =new Account(1,"张三","123456",18);
          //提交事务
        sqlSession.commit(); //查询不需要,增删改必须提交
        //关闭连接池
        sqlSession.close();
    }
}
通过Mapper代理实现自定义接口(重要)
  1. 自定义Mapper接口

    public interface AccountMapper {
        int add(Account account);
        int update(Account account);
        int deleteById(Integer id);
        List<Account> findAll();
        Account findById(Integer id);
    }
    

2.创建对应的Mapper.xml,定义接口方法对应的SQL语句。

标签可选insert,delete,update,select。

Mybatis框架会根据规则自动创建接口实现类的代理对象。(代理的是接口,代理对象为实现类)

映射规则

  • namespace属性值为接口的全类名。
  • id属性为接口中对应的方法名。
  • parameterType属性值和接口中对应方法传递的参数类型一致。
  • resultType属性值和接口中对应方法返回值类型一致(只有查用写,增删改都是返回int)。
@Test
public  void test2() {
InputStream InputStream = testMybatis.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
SqlSession sqlSession = Factory.openSession();
//获取实现接口的代理对象
AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
//增
Account account1 = new Account(1,"小风","14525",18);
mapper.add(account1);
sqlSession.commit();
//查
List<Account> accountList = mapper.findAll();
for (Account account:accountList
) {
System.out.println(account);
}
//删
mapper.deleteById(1);
sqlSession.commit();
//查
System.out.println(mapper.findById(2));
//改
Account account2 = new Account(3, "小雨", "145256", 18);
mapper.update(account2);
sqlSession.commit();
//关闭连接池
sqlSession.close();
}

总结

先解析resource文件夹下Config.xml文件配置的环境(如何连接数据库)和注册的mapper.xml文件。

Mapper.xml文件配置实体类(JavaBean)属性与数据库字段如何进行映射。

级联查询

class表

student表

Java实体类映射【Student】和【Classes】

@Data
public class Student {
    private Integer id;
    private String name;
    private Classes classes;
}
@Data
public class Classes {
    private Integer id;
    private String name;
    private List<Student> students;
}
连接查询
一对一

连接student表和class表,查询id为1的学生(包含所在班级名称)

SQL语句

select * from student s,class c where s.cid=c.id and s.id =1;

xml配置文件

<mapper namespace="com.Long.Mapper.StudentMapper">
<resultMap id="studentMap" type="com.Long.Entity.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<association property="classes" javaType="com.Long.Entity.Classes">
    <id column="cid" property="id"/>
    <result column="cname" property="name"/>
</association>
</resultMap>
<select id="findByIdAndClass" parameterType="Integer" resultMap="studentMap">
select s.id,s.name,c.id as cid,c.name as cname from student s,class c where s.id = #{id} and s.cid = c.id
</select>

总结

查询操作返回值映射

resultType属性

  • 直接映射,即根据数据库字段名称和Java对象属性名称和类型一一映射,

resultmap属性

  • 根据column属性(数据库字段名称)和property属性(Java对象属性名)进行名称映射的。
  • id标签是主键,result标签是普通字段
  • 包含多个字段的java对象需要association标签
  • 包含多个字段的java集合需要association标签
一对多

连接student表和class表,查询id为2的班级中所有学生信息

SQL语句

select s.id,s.name ,c.id,c.name from student s,class c where c.id =2 and s.cid = c.id

xml配置文件

<mapper namespace="com.Long.Mapper.StudentMapper">
<resultMap id="studentMap" type="com.Long.Entity.Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<association property="classes" javaType="com.Long.Entity.Classes">
    <id column="cid" property="id"/>
    <result column="cname" property="name"/>
</association>
</resultMap>
<select id="findByIdAndClass" parameterType="Integer" resultMap="studentMap">
select s.id,s.name ,c.id,c.name from student s,class c where s.id = #{id} and s.cid = c.id;
</select>

测试

@Test
public void test3() {
    InputStream InputStream = Student.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
    SqlSession sqlSession = Factory.openSession();
    //获取实现接口的代理对象
    ClassesMapper mapper = sqlSession.getMapper(ClassesMapper.class);
    System.out.println(mapper.findStudentsByClassId(2)); //返回的集合不用for循环遍历
    sqlSession.close();
}
多对多(一对多的升级)

逆向工程(代码自动生成)

传统的开发中上述的三个组件需要开发者手动创建,逆向工程可以帮助开发者来自动创建三个组件,减
轻开发者的工作量,提高工作效率。

MyBatis 框架需要(三个组件):

  • 实体类
  • 自定义 Mapper 接口
  • Mapper.xml

MyBatis Generator,简称 MBG,是⼀个专门为 MyBatis 框架开发者定制的代码⽣成器,可自动生成
MyBatis 框架所需上述三组件,也可支持基本的 CRUD 操作,但是⼀些相对复杂的 SQL 需要开发者自己来完成。

相关jar包
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>

创建 MBG 配置文件 config.xml

1、jdbcConnection 配置数据库连接信息。

2、javaModelGenerator 配置 JavaBean 的生成策略。

3、sqlMapGenerator 配置 SQL 映射文件生成策略。

4、javaClientGenerator 配置 Mapper 接口的生成策略。

5、table 配置目标数据表(tableName:表名,domainObjectName:JavaBean 类名)。

resouce目录下的config.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="testTables" targetRuntime="MyBatis3">
        <jdbcConnection
                driverClass="com.mysql.cj.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/mybatisExercise?useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"
                userId="root"
                password="77549252"
        />
        <javaModelGenerator targetPackage="com.Long.Entity"
                            targetProject="Genertor/src/main/java"/>
        <sqlMapGenerator targetPackage="com.Long.Mapper.XML"
                         targetProject="Genertor/src/main/java"/>
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.Long.Mapper" targetProject="Genertor/src/main/java">
        </javaClientGenerator>
        <table tableName="t_account" domainObjectName="Account"/>
    </context>
</generatorConfiguration>
Genertor类测试
public class Genertor {
    public static void main(String[] args) {
        List<String> warings = new ArrayList<String>();
        boolean overwrite = true;
        String genCig = "/config.xml";
        File configFile = new File(Genertor.class.getResource(genCig).getFile());
        ConfigurationParser configurationParser = new
                ConfigurationParser(warings);
        Configuration configuration = null;
        try {
            configuration = configurationParser.parseConfiguration(configFile);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (XMLParserException e) {
            e.printStackTrace();
        }
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = null;
        try {
            myBatisGenerator = new
                    MyBatisGenerator(configuration, callback, warings);
        } catch (InvalidConfigurationException e) {
            e.printStackTrace();
        }
        try {
            myBatisGenerator.generate(null);
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
目录结构

延迟加载 (懒加载)

延迟加载也叫懒加载、惰性加载,使⽤延迟加载可以提高程序的运行效率,针对于数据持久层的操左, 在某些特定的情况下去访问特定的数据库,在其他情况下可以不访问某些表,从⼀定程度上减少了 Java 应用与数据库的交互次数。

查询学生和班级的时,学生和班级是两张不同的表,如果当前需求只需要获取学生的信息,那么查询学生单表即可。

如果需要通过学生获取对应的班级信息,则必须查询两张表。

不同的业务需求,需要查询不同的表,根据具体的业务需求来动态减少数据表查询的工作就是延迟加载。

之前查询任务实现懒加载

连接student表和class表,查询id为1的学生(包含所在班级名称)

select * from student s,class c where s.cid=c.id and s.id =1;
  1. 拆分成两条SQL语句

  2. select * from  student where id =1;
    

    当需要班级信息时,需要执行下面SQL语句,id参数为第一条语句查询到的cid

    select * from  class where id =#{id};
    
  3. 懒加载目的:不需要获取班级信息的需求时不需要执行第二条sql语句,增加效率,根据需求可以动态改变。

    resouce目录下的config.xml配置文件配置懒加载

    <settings>
        <!-- 打印SQL-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    
  4. StudentMapper接口和ClassesMapper接口各定义查找方法

    // ClassesMapper接口
    public interface ClassesMapper {
        Classes findById(Integer id);
    }
    
    public interface StudentMapper {
        Student findById(Integer id);
    }
    
  5. 配置文件配置两条SQL语句的关系

    StudentMapper.xml文件下配置

    <mapper namespace="com.Long.Mapper.StudentMapper">
    <resultMap id="studentMap" type="com.Long.Entity.Student">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <collection property="classes" javaType="com.Long.Entity.Classes"
                    select="com.Long.Mapper.ClassesMapper.findById" column="cid"/>
    </resultMap>
    <select id="findById" parameterType="Integer" resultMap="studentMap">
        select * from  student where id =#{id};
    </select>
    </mapper>
    

    ClassesMapper.xml文件下配置

    <mapper namespace="com.Long.Mapper.ClassesMapper">
        <select id="findById" parameterType="Integer" resultType="com.Long.Entity.Classes">
            select * from  class where id =#{id};
    </select>
    </mapper>
    
  6. 测试

    @Test
    public void test3() {
        InputStream InputStream = test.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
        SqlSession sqlSession = Factory.openSession();
        StudentMapper StudentMapper = sqlSession.getMapper(StudentMapper.class);
        Student student = StudentMapper.findById(1);
        System.out.println(student.getName()); //懒加载下不需要加载班级信息,执行1条SQL语句
    //  System.out.println(student.getClasses()); //懒加载下需要加载班级信息,执行2条SQL语句
        sqlSession.close();
    }
    

缓存

使用缓存可以减少 Java 应用与数据库的交互次数,从而提升程序的运行效率。比如查询出 id = 1 的对
象,第⼀次查询出之后会⾃动将该对象保存到缓存中,当下⼀次查询时,直接从缓存中取出对象即可,
无需再次访问数据库。

分类
1、⼀级缓存:SqlSession 级别,默认开启,并且不能关闭。

操作数据库时需要创建SqlSession对象,在对象中有⼀个HashMap用于存储缓存数据,不同的SqlSession 之间缓存数据区域是互不影响的。

⼀级缓存的作用域是SqlSession范围的,当在同⼀个SqlSession中执行两次相同的 SQL 语句事,第⼀次执行完毕会将结果保存到缓存中,第二次查询时直接从缓存中获取。

需要注意的是,如果SqlSession执行了 DML 操作(insert、update、delete),MyBatis 必须将缓存清空以保证数据的准确性。

验证
  • 不同的SqlSession
@Test
public void test4() {
    InputStream InputStream = test.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
    SqlSession sqlSession = Factory.openSession();
    StudentMapper StudentMapper = sqlSession.getMapper(StudentMapper.class);
    Student student = StudentMapper.findById(1);
    System.out.println(student.getName());
    sqlSession.close();
    SqlSession sqlSession1 = Factory.openSession(); //创建不同的SqlSession
    StudentMapper StudentMapper1 = sqlSession1.getMapper(StudentMapper.class);
    Student student1 = StudentMapper1.findById(1);
    System.out.println(student1.getName());
    sqlSession1.close();
}

  • 同一SqlSession
@Test
public void test4() {
    InputStream InputStream = test.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
    SqlSession sqlSession = Factory.openSession();
    StudentMapper StudentMapper = sqlSession.getMapper(StudentMapper.class);
    Student student = StudentMapper.findById(1);
    Student student1 = StudentMapper.findById(1);
    System.out.println(student.getName());
    System.out.println(student1.getName());
    sqlSession.close();
}

2、二级缓存:Mapper级别,默认关闭,可以开启。
  • 使用二级缓存时,多个SqlSession使用同⼀个Mapper的 SQL 语句操作数据库,得到的数据会存在二级缓存区。
  • 同样是使用HashMap进行数据存储,相比较于⼀级缓存,二级缓存的范围更大,多个SqlSession 可以共用二级缓存,
  • 二级缓存是跨SqlSession的。

二级缓存是多个 SqlSession 共享的,其作用域是Mapper的同⼀个namespace,不同的SqlSession两次执行相同的 namespace 下的 SQL 语句,参数也相等,则第⼀次执行成功之后会将数据保存到二级缓存中,第二次可直接从二级缓存中取出数据。

Mybatis自带二级缓存
  • Resource目录下的config.xml文件配置

    <!-- 开启⼆级缓存 -->
    <setting name="cacheEnabled" value="true"/>
    
  • Mapper.xml配置

    <cache/>
    
  • Entity包下的实体类实现序列化接口

    @Data
    public class Student  implements Serializable {
        private Integer id;
        private String name;
        private Classes classes;
    }
    

验证

@Test
public void test4() {
    InputStream InputStream = test.class.getClassLoader().getResourceAsStream("SqlMapperConfig.xml");
    SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
    SqlSessionFactory Factory = sqlSessionFactoryBuilder.build(InputStream);
    SqlSession sqlSession = Factory.openSession();
    StudentMapper StudentMapper = sqlSession.getMapper(StudentMapper.class);
    Student student = StudentMapper.findById(1);
    System.out.println(student.getName());
    sqlSession.close();
    SqlSession sqlSession1 = Factory.openSession(); //创建不同的SqlSession
    StudentMapper StudentMapper1 = sqlSession1.getMapper(StudentMapper.class);
    Student student1 = StudentMapper1.findById(1);
    System.out.println(student1.getName());
    sqlSession1.close();
}

ehcache二级缓存
  • pom.xml导入相关jar包

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-ehcache</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.4.3</version>
    </dependency>
    
  • 添加Resource目录下的ehcache.xml,配置相关配置。

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
        <diskStore/>
        <defaultCache
                maxElementsInMemory="1000"
                maxElementsOnDisk="10000000"
                eternal="false"
                overflowToDisk="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
        </defaultCache>
    </ehcache>
    

    爆红请点击参考https://blog.csdn.net

  • Resource目录下的config.xml文件配置

    <!-- 开启⼆级缓存 -->
    <setting name="cacheEnabled" value="true"/>
    
  • Mapper.xml配置缓存策略

    <cache type="org.mybatis.caches.ehcache.EhcacheCache">
     <!-- 缓存创建之后,最后⼀次访问缓存的时间至缓存失效的时间间隔 -->
     <property name="timeToIdleSeconds" value="3600"/>
     <!-- 缓存⾃创建时间起⾄失效的时间间隔 -->
     <property name="timeToLiveSeconds" value="3600"/>
     <!-- 缓存回收策略,LRU表示移除近期使⽤最少的对象 -->
     <property name="memoryStoreEvictionPolicy" value="LRU"/>
    </cache>
    
  • Entity包下的实体类不需要实现序列化接口

    @Data
    public class Student {
        private Integer id;
        private String name;
        private Classes classes;
    }
    

动态SQL标签

使用动态SQL可简化代码的开发,减少开发者的工作量,程序可以自动根据业务参数来决定SQL的组成。

AccountMapper AccountMapper = sqlSession.getMapper(AccountMapper.class);
Account account = new Account(1,"小明","123",22);
System.out.println(AccountMapper.findByAccount(account));
Account accountOne = new Account("小明","123");
System.out.println(AccountMapper.findByAccount(accountOne));
<!--动态执行该SQL语句,当需要根据id和username查时不需要额外的语句-->
<select id="findByAccount" parameterType="com.Long.Entity.Account" resultType="com.Long.Entity.Account">
    select * from t_account where id =#{id} and username =#{username} and pwd=#{pwd} and age =#{age};
</select>

上述代码无动态SQL语句时,当只知道账户姓名和密码时确匹配失败,原因在于SQL语句多余传了默认值。

if 标签

if 标签可以自动根据表达式的结果来决定是否将对应的语句添加到 SQL 中,如果条件不成立则不添加, 如果条件成立则添加。

where 标签 (和if标签连用)

注意:where 标签不会检测SQL语句末尾多余的and并删除,因此and写在前面

where 标签可以自动判断是否要删除语句块中的 and 关键字,如果检测到 where 直接跟 and 拼接,则自动删除 and,通常情况下 if 和 where 结合起来使用。

<select id="findByAccount" parameterType="com.Long.Entity.Account" resultType="com.Long.Entity.Account">
    select * from t_account
    <where>
    <if test="id!=null">
         id =#{id}
    </if>
    <if test="username!=null">
        and  username =#{username}
    </if>
    <if test="pwd!=null">
        and  pwd=#{pwd}
    </if>
    <if test="age!=null">
        and age =#{age}
    </if>
    </where>
</select>
choose 、when 、otherwise 标签

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。choose执行过程中按顺序判断 when 中的条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when的条件都不满则时,则执行 otherwise 中的 sql。

<!--动态执行该SQL语句,当需要根据id和username查时不需要额外的语句-->
<select id="findByAccount" parameterType="com.Long.Entity.Account" resultType="com.Long.Entity.Account">
    select * from t_account
    <where>
    <choose>
    <when test="id!=null">
         id =#{id}
    </when>
    <when test="username!=null">
        and  username =#{username}
    </when>
    <when test="pwd!=null">
        and  pwd=#{pwd}
    </when>
    <when test="age!=null">
        and age =#{age}
    </when>
    <otherwise>
        <!--如果传入参数都为null那么就返回id=1的数据-->
        id = 1
    </otherwise>
    </choose>
    </where>
</select>
trim 标签

trim 标签中的 prefix 和 suffix 属性会被用于生成实际的 SQL 语句,会和标签内部的语句进行拼接,如果语句前后出现了 prefixOverrides或者suffixOverrides 属性中指定的值,MyBatis 框架会自动将其删除。

用trim标签实现where标签的作用

<!--where后面发现紧跟着and就自动删除-->
<trim prefix="where" prefixOverrides="and">
set 标签

set 标签用于 update 操作,会自动根据参数选择生成 SQL 语句。

静态更新SQL的问题
Account account = new Account(1,"小明","123",22);
System.out.println(AccountMapper.findByAccount(account));
account.setAge(18); //仅更改了年龄但SQL语句中其他属性进行了重复赋值
AccountMapper.update(account);
System.out.println(account);
<mapper namespace="com.Long.Mapper.AccountMapper">
<update id="update"  parameterType="com.Long.Entity.Account">
    update t_account set age=#{age},username =#{username},pwd=#{pwd} where id =#{id}
</update>
增加set标签
<mapper namespace="com.Long.Mapper.AccountMapper">
<update id="update"  parameterType="com.Long.Entity.Account">
update t_account
<set>
    <choose>
    <when test="username!=null">
        and  username =#{username}
    </when>
    <when test="pwd!=null">
        and  pwd=#{pwd}
    </when>
    <when test="age!=null">
        and age =#{age}
    </when>
    </choose>
</set>
where id = #{id}
</update>

foreach 标签

foreach 标签可以迭代生成⼀系列值,这个标签主要用于 SQL 的 in 语句。

举例

仅查询id=1,2,4的账户信息

静态SQL语句
select * from t_account where id in(1,2,4);
动态SQL(字符串拼接)
<select id="findByIds" parameterType="com.Long.Entity.Account" resultType="com.Long.Entity.Account">
select * from t_account
<where>
    <foreach collection="ids" open="id in (" close=")" item="id"
             separator=",">
        #{id}
    </foreach>
</where>
</select>
测试
ArrayList<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(2);
ids.add(4);
Account account = new Account();
account.setIds(ids);
System.out.println(AccountMapper.findByIds(account));


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Steve_hanhaiLong

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值