MyBatis

1. MyBatis概述

Mybatis:和数据库进行交互,持久化层框架(SQL映射框架)。

从原始的JDBC----dbutils----JdbcTemplate;成为工具(不用)

  1. 原生JDBC:连接数据库–>获取PeraredStatment–>写sql–>预编译参数–>执行sql封装结果。
  2. sql语句是硬编码在Java程序中(耦合:数据库层和java编码)。

MyBatis优点:

  1. MyBatis将重要的步骤抽取出来可以人工定制,其他步骤自动化。

  2. 重要的步骤都是写在配置文件中的(好维护);

  3. 完全解决数据库的优化问题。

  4. MyBatis底层就是对原生JDBC的简单封装。

  5. 既将Java编码与sql抽取出来,还不会失去自动化,半自动的持久化框架。

2. 快速开始

项目结构如下:

项目结构
  1. 创建数据库和Employee数据表

截屏2021-08-19 20.48.33.png

  1. 创建数据表对应的POJO
public class Employee {
   private Integer id;
   private String lastName;
   private String email;
   private String gender;
   ...
}
  1. 导入jar包:
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.11</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.2.8</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>RELEASE</version>
        <scope>compile</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.3.0</version>
    </dependency>
</dependencies>
  1. 创建全局配置文件:mybatis-config.xml
  • 导入jdbc.properties
  • 从jdbc.properties中读取数据库信息
  • 将sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(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="jdbc.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!-- 从配置文件中加载属性 -->
                <property name="driver" value="${driverClass}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${user}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
   <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
   <mappers>
      <mapper resource="EmployeeMapper.xml" />
   </mappers>
</configuration>
  1. 创建DAO:EmployeeMapper
public interface EmployeeMapper {
   public Employee getEmpById(Integer id);
}
  1. 创建Mapper映射文件:EmployeeMapper.xml
  • namespace:名称空间;指定为接口的全类名
  • id:唯一标识,与接口的方法一定同名
  • resultType:返回值类型,与接口的返回值类型相同
  • #{id}:从传递过来的参数中取出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.xz.mybatis.dao.EmployeeMapper">
<!-- 
namespace:名称空间;指定为接口的全类名
id:唯一标识
resultType:返回值类型
#{id}:从传递过来的参数中取出id值

public Employee getEmpById(Integer id);
 -->
   <select id="getEmpById" resultType="com.xz.mybatis.bean.Employee">
      select id,last_name lastName,email,gender from tbl_employee where id = #{id}
   </select>
</mapper>
  1. 编写测试类

/**
 * 1、接口式编程
 *     原生:       Dao       ====>  DaoImpl
 *     mybatis:   Mapper ====>  xxMapper.xml
 * 
 * 2、SqlSession代表和数据库的一次会话;用完必须关闭;
 * 3、SqlSession和connection一样都是非线程安全。每次使用都应该去获取新的对象。
 * 4、mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。
 *        (将接口和xml进行绑定)
 *        EmployeeMapper empMapper = sqlSession.getMapper(EmployeeMapper.class);
 * 5、两个重要的配置文件:
 *        mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息等...系统运行环境信息
 *        sql映射文件:保存了每一个sql语句的映射信息:将sql抽取出来。
 */
public class MyBatisTest {
   public SqlSessionFactory getSqlSessionFactory() throws IOException {
      String resource = "mybatis-config.xml";
      InputStream inputStream = Resources.getResourceAsStream(resource);
      return new SqlSessionFactoryBuilder().build(inputStream);
   }

   /**
    * 1、根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象 有数据源一些运行环境信息
    * 2、sql映射文件;配置了每一个sql,以及sql的封装规则等。 
    * 3、将sql映射文件注册在全局配置文件中
    * 4、写代码:
    *        1)、根据全局配置文件得到SqlSessionFactory;
    *        2)、使用sqlSession工厂,获取到sqlSession对象使用他来执行增删改查
    *           一个sqlSession就是代表和数据库的一次会话,用完关闭
    *        3)、使用sql的唯一标志来告诉MyBatis执行哪个sql。sql都是保存在sql映射文件中的。
    * @throws IOException
    */
   @Test
   public void test() throws IOException {

      // 2、获取sqlSession实例,能直接执行已经映射的sql语句
      // sql的唯一标识:statement Unique identifier matching the statement to use.
      // 执行sql要用的参数:parameter A parameter object to pass to the statement.
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();

      SqlSession openSession = sqlSessionFactory.openSession();
      try {
         Employee employee = openSession.selectOne(
               "com.xz.mybatis.EmployeeMapper.selectEmp", 1);
         System.out.println(employee);
      } finally {
         openSession.close();
      }
   }

   @Test
   public void test01() throws IOException {
      // 1、获取sqlSessionFactory对象
      SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
      // 2、获取sqlSession对象
      SqlSession openSession = sqlSessionFactory.openSession();
      try {
         //3、获取接口的实现类对象
         //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
         EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
         Employee employee = mapper.getEmpById(1);
         System.out.println(mapper.getClass());
         System.out.println(employee);
      } finally {
         openSession.close();
      }
   }
}

3. 全局配置文件设置

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>
   <!--
      1、mybatis可以使用properties来引入外部properties配置文件的内容;
      resource:引入类路径下的资源
      url:引入网络路径或者磁盘路径下的资源
     -->
   <properties resource="dbconfig.properties"></properties>
   
   
   <!-- 
      2、settings包含很多重要的设置项
      setting:用来设置每一个设置项
         name:设置项名
         value:设置项取值
    -->
   <settings>
      <setting name="mapUnderscoreToCamelCase" value="true"/>
   </settings>
   
   
   <!-- 3、typeAliases:别名处理器:可以为我们的java类型起别名 
         别名不区分大小写
   -->
   <typeAliases>
      <!-- 1、typeAlias:为某个java类型起别名
            type:指定要起别名的类型全类名;默认别名就是类名小写;employee
            alias:指定新的别名
       -->
      <!-- <typeAlias type="com.xz.mybatis.bean.Employee" alias="emp"/> -->
      
      <!-- 2、package:为某个包下的所有类批量起别名 
            name:指定包名(为当前包以及下面所有的后代包的每一个类都起一个默认别名(类名小写),)
      -->
      <package name="com.xz.mybatis.bean"/>
      
      <!-- 3、批量起别名的情况下,使用@Alias注解为某个类型指定新的别名 -->
   </typeAliases>
      
   <!-- 
      4、environments:环境们,mybatis可以配置多种环境 ,default指定使用某种环境。可以达到快速切换环境。
         environment:配置一个具体的环境信息;必须有两个标签;id代表当前环境的唯一标识
            transactionManager:事务管理器;
               type:事务管理器的类型;JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory)
                  自定义事务管理器:实现TransactionFactory接口.type指定为全类名
            
            dataSource:数据源;
               type:数据源类型;UNPOOLED(UnpooledDataSourceFactory)
                        |POOLED(PooledDataSourceFactory)
                        |JNDI(JndiDataSourceFactory)
               自定义数据源:实现DataSourceFactory接口,type是全类名
       -->
       

       
   <environments default="dev_mysql">
      <environment id="dev_mysql">
         <transactionManager type="JDBC"></transactionManager>
         <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>
   
      <environment id="dev_oracle">
         <transactionManager type="JDBC" />
         <dataSource type="POOLED">
            <property name="driver" value="${orcl.driver}" />
            <property name="url" value="${orcl.url}" />
            <property name="username" value="${orcl.username}" />
            <property name="password" value="${orcl.password}" />
         </dataSource>
      </environment>
   </environments>
   
   
   <!-- 5、databaseIdProvider:支持多数据库厂商的;
       type="DB_VENDOR":VendorDatabaseIdProvider
         作用就是得到数据库厂商的标识(驱动getDatabaseProductName()),mybatis就能根据数据库厂商标识来执行不同的sql;
         MySQL,Oracle,SQL Server,xxxx
     -->
   <databaseIdProvider type="DB_VENDOR">
      <!-- 为不同的数据库厂商起别名 -->
      <property name="MySQL" value="mysql"/>
      <property name="Oracle" value="oracle"/>
      <property name="SQL Server" value="sqlserver"/>
   </databaseIdProvider>
   
   
   <!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
   <!-- 6、mappers:将sql映射注册到全局配置中 -->
   <mappers>
      <!-- 
         mapper:注册一个sql映射 
            注册配置文件
            resource:引用类路径下的sql映射文件
               mybatis/mapper/EmployeeMapper.xml
            url:引用网路路径或者磁盘路径下的sql映射文件
               file:///var/mappers/AuthorMapper.xml
               
            注册接口
            class:引用(注册)接口,
               1、有sql映射文件,映射文件名必须和接口同名,并且放在与接口同一目录下;
               2、没有sql映射文件,所有的sql都是利用注解写在接口上;
               推荐:
                  比较重要的,复杂的Dao接口我们来写sql映射文件
                  不重要,简单的Dao接口为了开发快速可以使用注解;
      -->
      <!-- <mapper resource="mybatis/mapper/EmployeeMapper.xml"/> -->
      <!-- <mapper class="com.xz.mybatis.dao.EmployeeMapperAnnotation"/> -->
      
      <!-- 批量注册: -->
      <package name="com.xz.mybatis.dao"/>
   </mappers>
</configuration>

3.1 properties

mybatis可以使用properties来引入外部properties配置文件的内容;
resource:引入类路径下的资源
url:引入网络路径或者磁盘路径下的资源

 <properties resource="dbconfig.properties"></properties>

   <environments default="dev_mysql">
      <environment id="dev_mysql">
         <transactionManager type="JDBC"></transactionManager>
         <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>

3.2 settings

settings包含很多重要的设置项
setting:用来设置每一个设置项
name:设置项名
value:设置项取值

   <settings>
      <setting name="mapUnderscoreToCamelCase" value="true"/>
   </settings>

3.3 typeAliases

typeAliases:别名处理器:可以为我们的java类型起别名;别名不区分大小写,一般推荐不用别名。

  • 方式一:给全类名起别名
<typeAliases>
    <!-- 以后在Mapper.xml中使用此类型时无需再写全类名,直接写User即可 -->
    <typeAlias type="com.qizegao.pojo.User" alias="User"/>
</typeAliases>
  • 方式二:扫描指定包下的类,某一类的别名默认是类名首字母小写
<typeAliases>
    <!-- 此包下的User类的别名成为user -->
    <package name="com.qizegao.pojo"/>
</typeAliases>

注意:可以在对应的类上加注解@Alias(“xxx”),则类名的别名成为指定的xxx

3.4 environments

  1. environments:环境们,mybatis可以配置多种环境 ,default指定使用某种环境。可以达到快速切换环境。
  2. environment:配置一个具体的环境信息;必须有两个标签;id代表当前环境的唯一标识
  3. transactionManager:事务管理器;
    1. type:
      1. 事务管理器的类型:JDBC(JdbcTransactionFactory)|MANAGED(ManagedTransactionFactory)
      2. 自定义事务管理器:实现TransactionFactory接口.type指定为全类名
    2. dataSource:数据源; type:数据源类型;UNPOOLED(UnpooledDataSourceFactory);|POOLED(PooledDataSourceFactory);|JNDI(JndiDataSourceFactory)自定义数据源:实现DataSourceFactory接口,type是全类名
<!--配置两个环境;通过default切换环境-->
<environments default="dev_mysql">
  <!--第一个环境;id标识不同的环境-->
   <environment id="dev_mysql">
      <transactionManager type="JDBC"></transactionManager>
      <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>
  
<!--第二个环境;oracle需要在properties文件里面配置参数-->
   <environment id="dev_oracle">
      <transactionManager type="JDBC" />
      <dataSource type="POOLED">
         <property name="driver" value="${orcl.driver}" />
         <property name="url" value="${orcl.url}" />
         <property name="username" value="${orcl.username}" />
         <property name="password" value="${orcl.password}" />
      </dataSource>
   </environment>
</environments>

3.5 databaseIdProvider

databaseIdProvider:支持多数据库厂商的;
type=“DB_VENDOR”:VendorDatabaseIdProvider
作用就是得到数据库厂商的标识(驱动getDatabaseProductName()),mybatis就能根据数据库厂商标识来执行不同的sql;
MySQL,Oracle,SQL Server,xxxx

<databaseIdProvider type="DB_VENDOR">
   <!-- 为不同的数据库厂商起别名 -->
   <property name="MySQL" value="mysql"/>
   <property name="Oracle" value="oracle"/>
   <property name="SQL Server" value="sqlserver"/>
</databaseIdProvider>

使用:

  1. 使用不同的环境需要在environments里面切换环境
  2. 在mapper里面需要用databaseId标识使用的数据库。
<select id="getEmpById" resultType="com.xz.mybatis.bean.Employee"
   databaseId="mysql">
   select * from tbl_employee where id = #{id}
</select>
<select id="getEmpById" resultType="com.xz.mybatis.bean.Employee"
   databaseId="oracle">
   select EMPLOYEE_ID id,LAST_NAME    lastName,EMAIL email 
   from employees where EMPLOYEE_ID=#{id}
</select>

3.6 mappers

mappers:将sql映射注册到全局配置中

  • 方式一:resource:引用类路径下的sql映射文件
<mapper resource="mybatis/mapper/EmployeeMapper.xml"/>
  • 方式二:url:引用网路路径或者磁盘路径下的sql映射文件

  • 方式三:class:引用(注册)接口

    • 有mapper文件:映射文件名必须和接口同名,并且放在与接口同一目录下;
    • 没有mapper文件:所有的sql都是利用注解写在接口上;
<mapper class="com.xz.mybatis.dao.EmployeeMapperAnnotation"/>
public interface EmployeeMapperAnnotation {
   @Select("select * from tbl_employee where id=#{id}")
   public Employee getEmpById(Integer id);
}
  • 方式四:package:同class。

4. SQL映射文件

EmployeeMapper.xml内容:

<mapper namespace="com.xz.dao.EmployeeMapper">
      <select id="getEmpByLastNameLikeReturnMap" resultType="java.util.Map">
        select * from Employee where email like #{lastName}
    </select>
  
    <select id="getEmpByIdReturnMap" resultType="java.util.Map">
        select id,last_name,email,gender from Employee where id=#{id};
    </select>

    <select id="getEmpsByLastNameLike" resultType="com.xz.bean.Employee">
        select * from Employee where last_name like #{lastName};
    </select>
  
    <select id="getEmpByList" resultType="com.xz.bean.Employee">
        select id,last_name,email,gender from Employee where id=#{list[0]};
    </select>

    <select id="getEmpByMap" resultType="com.xz.bean.Employee">
        select id,last_name,email,gender from ${table} where id=#{id} and last_name=#{lastName};
    </select>

    <select id="getEmpByIdAndLastName" resultType="com.xz.bean.Employee">
        select id,last_name,email,gender from Employee where id=#{id} and last_name=#{last_name};
    </select>
    <!--    public Employee getEmpById(Integer id);-->
    <select id="getEmpById" resultType="com.xz.bean.Employee">
        select id,last_name,email,gender from Employee where id=#{id};
    </select>


    <!--public void addEmp(Employee employee);-->
    <!--parameterType:传入的参数,可以省略-->
    <insert id="addEmp" parameterType="com.xz.bean.Employee"
    useGeneratedKeys="true" keyProperty="id">
        insert into Employee(last_name,email,gender) values (#{lastName},#{email},#{gender});
    </insert>

    <!--public void updateEmp(Employee employee);-->
    <update id="updateEmp">
        update Employee
        set last_name=#{lastName},
            email=#{email},
            gender=#{gender}
        where id = #{id};
    </update>

    <delete id="deleteEmpById">
        delete from Employee where id=#{id};
    </delete>
</mapper>

EmployeeMapper.java内容:

public interface EmployeeMapper {
    @MapKey("last_name")
    public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);

    public Map<String, Object> getEmpByIdReturnMap(Integer id);

    public List<Employee> getEmpsByLastNameLike(String lastName);
  
    public Employee getEmpByList(List<Integer> ids);
  
    public Employee getEmpByMap(Map<String, Object> map);

    public Employee getEmpByIdAndLastName(@Param("id") Integer id, @Param("last_name") String lastName);

    public Employee getEmpById(Integer id);

    public void addEmp(Employee employee);

    public void updateEmp(Employee employee);

    public void deleteEmpById(Integer id);
}

4.1 传入唯一参数

若传入参数只有唯一值,则填入任何参数都可以。例如这里的#{id}也可以写成#{idabc}

resultType:返回的对象

<!--    public Employee getEmpById(Integer id);-->
<select id="getEmpById" resultType="com.xz.bean.Employee">
    select id,last_name,email,gender from Employee where id=#{id};
</select>

4.2 传入对象

若传入的是一个对象参数,例如这里的Employee,则在value里面填入Employee对象的相关属性即可。

parameterType:传入的参数,可以省略.

values (#{lastName},#{email},#{gender});

<insert id="addEmp" parameterType="com.xz.bean.Employee"
useGeneratedKeys="true" keyProperty="id">
    insert into Employee(last_name,email,gender) values (#{lastName},#{email},#{gender});
</insert>

4.3 传入多个参数

4.3.1 有@Param()注解

  • 在接口方法对应的行参前面加上@Param(“”)注解,可以在mapper文件中直接使用传入的参数。@Param(“id”) Integer id,
public Employee getEmpByIdAndLastName(@Param("id") Integer id, @Param("last_name") String lastName);
  • 在Mapper文件中:这里的id和last_name必须要和接口方法对应。id=#{id}
<select id="getEmpByIdAndLastName" resultType="com.xz.bean.Employee">
    select id,last_name,email,gender from Employee where id=#{id} and last_name=#{last_name};
</select>

4.3.2 无@Param()注解

  • 普通方法,没有注解:
public Employee getEmpByIdAndLastName(Integer id, String lastName);
  • 在Mapper文件中必须使用param1…paramN或者是0…N-1:id=#{param1}
<select id="getEmpByIdAndLastName" resultType="com.xz.bean.Employee">
    select id,last_name,email,gender from Employee where id=#{param1} and last_name=#{param2};
</select>

或者:id=#{0}

<select id="getEmpByIdAndLastName" resultType="com.xz.bean.Employee">
    select id,last_name,email,gender from Employee where id=#{0} and last_name=#{1};
</select>

4.3.3传入Map

若想传入多个参数,也可以在接口方法中传入一个map

public Employee getEmpByMap(Map<String, Object> map);

在Mapper文件中:id=#{id} and last_name=#{lastName};

<select id="getEmpByMap" resultType="com.xz.bean.Employee">
    select id,last_name,email,gender from Employee where id=#{id} and last_name=#{lastName};
</select>

则在测试类中传入map即可,但是注意键值对之间的对应:map.put(“id”, 1); map.put(“lastName”, “xz”);

@Test
public void test07() throws IOException {
    SqlSession openSession = getSqlSessionFactory().openSession();
    EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
    try {
        Map map = new HashMap();
        map.put("id", 1);
        map.put("lastName", "xz");
        Employee xz = mapper.getEmpByMap(map);
        System.out.println(xz);
    } finally {
        openSession.close();
    }
}

4.3.4 返回集合

resultType:如果返回的是一个集合,要写集合中元素的类型,而非List类型

<!-- public List<Employee> getEmpsByLastNameLike(String lastName); -->
<!--resultType:如果返回的是一个集合,要写集合中元素的类型  -->
<select id="getEmpsByLastNameLike" resultType="com.xz.mybatis.bean.Employee">
   select * from tbl_employee where last_name like #{lastName}
</select>
public List<Employee> getEmpsByLastNameLike(String lastName);

4.3.5 返回Map

  1. 返回的是一条map信息:

    这里idea会报错没有@Mapkey(),但是因为是返回一条map信息,所以运行没有异常。key就是列名,值就是对应的值。

//返回一条记录的map;key就是列名,值就是对应的值
public Map<String, Object> getEmpByIdReturnMap(Integer id);
<!--public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->
<select id="getEmpByIdReturnMap" resultType="map">
   select * from tbl_employee where id=#{id}
</select>

控制台输出信息:{gender=0, last_name=jerry, id=2, email=jerry@qq.com}

  1. 返回多条map

此时需要注解@Mapkey(),表示哪个属性作为map的key

//多条记录封装一个map:Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean
//@MapKey:告诉mybatis封装这个map的时候使用哪个属性作为map的key
@MapKey("lastName")
public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);
<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);  -->
<select id="getEmpByLastNameLikeReturnMap" resultType="com.xz.mybatis.bean.Employee">
   select * from tbl_employee where last_name like #{lastName}
</select>

控制台输出信息:{xz={gender=1, last_name=xz, id=1, email=zxxz@qqcom}, ZELDA={gender=0, last_name=ZELDA, id=9, email=ZELDA@qq.com}}

4.4 ${}和#{}

#{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入

${}:取出的值直接拼装在sql语句中;会有安全问题;

例如:${}直接将id拼在sql语句中

select * from tbl_employee where id=${id} and last_name=#{lastName}
Preparing: select * from tbl_employee where id=2 and last_name=?

一般不推荐使用 , 但 是 在 下 面 这 些 情 况 时 只 能 只 用 {},但是在下面这些情况时只能只用 {}:

  • 原生jdbc不支持占位符的地方我们就可以使用${}进行取值
    比如分表、排序。。。;按照年份分表拆分

       select * from ${year}_salary where xxx;
       select * from tbl_employee order by ${f_name} ${order}
    

5. 映射文件进阶

文件结构:

截屏2021-08-19 20.59.49.png

在Employee表的基础上再创建tbl_dept表,其中Employee表d_id外链接于tbl_dept表:

截屏2021-08-19 21.01.42.png

  1. Employee.java
public class Employee {
    private Integer id;
    private String lastName;
    private String email;
    private String gender;
    private Department department;
    ...
}
  1. Department.java
public class Department {
    private Integer id;
    private String departmentName;
    private List<Employee> emps;
  ...
}
  1. DepartmentMapper.java
public interface DepartmentMapper {
    public Department getDeptById(Integer id);

    public Department getDeptByIdPlus(Integer id);

    public Department getDeptByIdStep(Integer id);
}
  1. EmployeeMapperPlus.java
public interface EmployeeMapperPlus {

    public Employee getEmpById(Integer id);

    public Employee getEmpAndDept(Integer id);

    public Employee getEmpByIdStep(Integer id);

    public List<Employee> getEmpsByDeptId(Integer deptId);

}
  1. EmployeeMapperPlus.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="com.xz.dao.EmployeeMapperPlus">

    <resultMap id="MySimpleEmp" type="com.xz.bean.Employee">
        <id column="id" property="id"></id>
        <result column="last_name" property="lastName"/>
        <result column="gender" property="gender"/>
    </resultMap>
    <select id="getEmpById" resultMap="MySimpleEmp">
        select * from Employee where id=#{id};
    </select>
    

    <resultMap id="MyDifEmp1" type="com.xz.bean.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <result column="d_id" property="department.id"/>
        <result column="dept_name" property="department.departmentName"/>
    </resultMap>
    <resultMap id="MyDifEmp2" type="com.xz.bean.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <association property="department" javaType="com.xz.bean.Department">
            <id column="d_id" property="id"/>
            <result column="dept_name" property="departmentName"/>
        </association>
    </resultMap>
    <select id="getEmpAndDept" resultMap="MyDifEmp2">
        SELECT e.id,e.last_name,e.email,e.gender,e.d_id,d.dept_name FROM Employee e,tbl_dept d WHERE e.d_id=d.id and e.id=#{id};
    </select>
    
    
    <resultMap id="MyEmpByStep" type="com.xz.bean.Employee">
        <id column="id" property="id"/>
        <result column="last_name" property="lastName"/>
        <association property="department" select="com.xz.dao.DepartmentMapper.getDeptById" column="d_id"/>
    </resultMap>
    <select id="getEmpByIdStep" resultMap="MyEmpByStep">
        select * from Employee where id=#{id};
    </select>

    <select id="getEmpsByDeptId" resultType="com.xz.bean.Employee">
        select * from Employee where d_id=#{deptId};
    </select>
</mapper>
  1. DepartmentMapper.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="com.xz.dao.DepartmentMapper">

    <select id="getDeptById" resultType="com.xz.bean.Department">
        select id,dept_name departmentName FROM tbl_dept WHERE id=#{id};
    </select>
    
    <resultMap id="MyDept" type="com.xz.bean.Department">
        <id column="did" property="id"/>
        <result column="dept_name" property="departmentName"/>
        <collection property="emps" ofType="com.xz.bean.Employee">
            <id column="id" property="id"/>
            <result column="last_name" property="lastName"/>
            <result column="email" property="email"/>
            <result column="gender" property="gender"/>
            <association property="department" javaType="com.xz.bean.Department">
                <id column="id" property="id"/>
                <result column="dept_name" property="departmentName"/>
            </association>
        </collection>
    </resultMap>

    <select id="getDeptByIdPlus" resultMap="MyDept">
        SELECT e.id, e.last_name, e.email, e.gender, d.id did, d.dept_name
        FROM tbl_dept d
                 LEFT JOIN Employee e ON e.d_id = d.id
        WHERE d.id = #{id};
    </select>

    <resultMap id="MyDeptStep" type="com.xz.bean.Department">
        <id column="id" property="id"/>
        <result column="dept_name" property="departmentName"/>
        <collection property="emps" select="com.xz.dao.EmployeeMapperPlus.getEmpsByDeptId" column="{deptId=id}"/>
    </resultMap>
    <select id="getDeptByIdStep" resultMap="MyDeptStep">
        select id, dept_name
        from tbl_dept
        where id = #{id};
    </select>
</mapper>

5.1 resultMap

resultMap:可以指定sql语句中和java对象所对应的值。

在中不需要写resultType,而写resultMap对应的id值

id定义主键会底层有优化;
column:指定哪一列
property:指定对应的javaBean属性

  • 其中last_name是sql中的属性,而lastName是javaBean中的属性,不需要开启驼峰命名规则,在result中即可对应。

<resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp">
   <!--指定主键列的封装规则
   id定义主键会底层有优化;
   column:指定哪一列
   property:指定对应的javaBean属性
     -->
   <id column="id" property="id"/>
   <!-- 定义普通列封装规则 -->
   <result column="last_name" property="lastName"/>
   <!-- 其他不指定的列会自动封装:我们只要写resultMap就把全部的映射规则都写上。 -->
   <result column="email" property="email"/>
   <result column="gender" property="gender"/>
</resultMap>

<!-- resultMap:自定义结果集映射规则;  -->
<!-- public Employee getEmpById(Integer id); -->
<select id="getEmpById"  resultMap="MySimpleEmp">
   select * from tbl_employee where id=#{id}
</select>

5.2 普通联合查询

联合查询:级联属性封装结果集

property使用:对象属性.属性。

<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="gender" property="gender"/>
   <result column="did" property="dept.id"/>
   <result column="dept_name" property="dept.departmentName"/>
</resultMap>
<select id="getEmpAndDept" resultMap="MyDifEmp">
    SELECT e.id,e.last_name,e.email,e.gender,e.d_id,d.dept_name FROM Employee e,tbl_dept d WHERE e.d_id=d.id and e.id=#{id};
</select>

5.3 association联合查询

使用association定义关联的单个对象的封装规则;和上述的普通的联合查询效果一致。

​ association可以指定联合的javaBean对象
property=“dept”:指定哪个属性是联合的对象
javaType:指定这个属性对象的类型[不能省略]

<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="gender" property="gender"/>
   
   <!--  association可以指定联合的javaBean对象
   property="dept":指定哪个属性是联合的对象
   javaType:指定这个属性对象的类型[不能省略]
   -->
   <association property="dept" javaType="com.atguigu.mybatis.bean.Department">
      <id column="did" property="id"/>
      <result column="dept_name" property="departmentName"/>
   </association>
</resultMap>
<!--  public Employee getEmpAndDept(Integer id);-->
<select id="getEmpAndDept" resultMap="MyDifEmp">
   SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
   d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
   WHERE e.d_id=d.id AND e.id=#{id}
</select>

5.4 association分步查询

1、先按照员工id查询员工信息
2、根据查询员工信息中的d_id值去部门表查出部门信息
3、部门设置到员工中;
  1. 先按照员工id查询员工信息:在EmployeeMapperPlus中:

这里通过方法传入的id值可以获取到对应employee所有的信息,包括department的d_id

<select id="getEmpByIdStep" resultMap="MyEmpByStep">
    select last_name,email,gender,d_id from Employee where id=#{id};
</select>
  1. 根据查询员工信息中的d_id值去部门表查出部门信息

这里传入的id=#{id}就是从上面的d_id传入的,但是名字问题用下面代码解答:

<!--public Department getDeptById(Integer id);  -->
<select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department">
   select id,dept_name departmentName from tbl_dept where id=#{id}
</select>
  1. 部门设置到员工中:使用association


property=“dept” :是需要设置的Employee中department中对应的dept属性。

column=“d_id”:在select语句中得到的结果,需要传入到.DepartmentMapper的getDeptById方法的值。

select=“com.atguigu.mybatis.dao.DepartmentMapper.getDeptById”:i_id需要传入的地址。

由上面分析可以知道,EmployeeMapperPlus全部代码如下

<!--  id  last_name  email   gender    d_id   -->
<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="email" property="email"/>
   <result column="gender" property="gender"/>
   <!-- association定义关联对象的封装规则
      select:表明当前属性是调用select指定的方法查出的结果
      column:指定将哪一列的值传给这个方法
      流程:使用select指定的方法(传入column指定的这列参数的值)查出对象,并封装给property指定的属性
    -->
   <association property="dept" 
      select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
      column="d_id">
   </association>
</resultMap>
<!--  public Employee getEmpByIdStep(Integer id);-->
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
   select * from tbl_employee where id=#{id}
</select>

5.5 collection联合查询

查询部门的时候将部门对应的所有员工信息也查询出来:

在DepartmentMapper中:ofType:指定集合里面元素的类型

<!--嵌套结果集的方式,使用collection标签定义关联的集合类型的属性封装规则  -->
<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept">
   <id column="did" property="id"/>
   <result column="dept_name" property="departmentName"/>
   <!-- 
      collection定义关联集合类型的属性的封装规则 
      ofType:指定集合里面元素的类型
   -->
   <collection property="emps" ofType="com.atguigu.mybatis.bean.Employee">
      <!-- 定义这个集合中元素的封装规则 -->
      <id column="eid" property="id"/>
      <result column="last_name" property="lastName"/>
      <result column="email" property="email"/>
      <result column="gender" property="gender"/>
   </collection>
</resultMap>
<!-- public Department getDeptByIdPlus(Integer id); -->
<select id="getDeptByIdPlus" resultMap="MyDept">
   SELECT d.id did,d.dept_name dept_name,
         e.id eid,e.last_name last_name,e.email email,e.gender gender
   FROM tbl_dept d
   LEFT JOIN tbl_employee e
   ON d.id=e.d_id
   WHERE d.id=#{id}
</select>

5.6 collection分步查询

这里和association步骤类似,不多做赘述。

在DepartmentMapper中:

<!-- collection:分段查询 -->
<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep">
   <id column="id" property="id"/>
   <id column="dept_name" property="departmentName"/>
   <collection property="emps" 
      select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
      column="{deptId=id}" fetchType="lazy"></collection>
</resultMap>
<!-- public Department getDeptByIdStep(Integer id); -->
<select id="getDeptByIdStep" resultMap="MyDeptStep">
   select id,dept_name from tbl_dept where id=#{id}
</select>

在EmployeeMapperPlus中:注意这里返回的employee是多个值,是List

<!-- public List<Employee> getEmpsByDeptId(Integer deptId); -->
<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
   select * from tbl_employee where d_id=#{deptId}
</select>

注意⚠️

可以看到collection和association是类似的,两者都是在两个相关的表中实现联合查询。

同时:和中**column="{deptId=id}"**可以传入多个值,也可以向即中传入多个值。

fetchType=“lazy”:在这里也可以实现懒加载。

但是两者具有一定的区别:collection主要是实现在两个表都返回一条记录时使用;而association主要是在其中一条记录值是List时使用

而且在中使用的是javaType,而是ofType。

5.6 懒加载

可以使用延迟加载(懒加载);(按需加载)
Employee==>Dept:
我们每次查询Employee对象的时候,都将一起查询出来。
部门信息在我们使用的时候再去查询;
分段查询的基础之上加上两个配置:

在mybatis-config.xml中:

<settings>
   <!--显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题  -->
   <setting name="lazyLoadingEnabled" value="true"/>
   <setting name="aggressiveLazyLoading" value="false"/>
</settings>

5.7 鉴别器


鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为
封装Employee:
如果查出的是女生:就把部门信息查询出来,否则不查询;
如果是男生,把last_name这一列的值赋值给email;

<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis">
   <id column="id" property="id"/>
   <result column="last_name" property="lastName"/>
   <result column="email" property="email"/>
   <result column="gender" property="gender"/>
   <!--
      column:指定判定的列名
      javaType:列值对应的java类型  -->
   <discriminator javaType="string" column="gender">
      <!--女生  resultType:指定封装的结果类型;不能缺少。/resultMap-->
      <case value="0" resultType="com.atguigu.mybatis.bean.Employee">
         <association property="dept" 
         select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
         column="d_id">
      </association>
      </case>
      <!--男生 ;如果是男生,把last_name这一列的值赋值给email; -->
      <case value="1" resultType="com.atguigu.mybatis.bean.Employee">
      <id column="id" property="id"/>
      <result column="last_name" property="lastName"/>
      <result column="last_name" property="email"/>
      <result column="gender" property="gender"/>
      </case>
   </discriminator>
</resultMap>

6. 动态SQL

动态SQL:一种更复杂的查询,可以设置各种查询条件。

  1. EmployeeMapperDynamic.java
public interface EmployeeMapperDynamic {

    public List<Employee> getEmpsByConditionIf(Employee employee);

    public List<Employee> getEmpsByConditionTrim(Employee employee);

    public List<Employee> getEmpsByConditionChoose(Employee employee);

    public void updateEmp(Employee employee);

    public List<Employee> getEmpsByConditionForeach(@Param("ids")List<Integer> ids);

    public void addEmps(@Param("emps")List<Employee> emps);
}
  1. EmployeeMapperDynamic.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="com.xz.dao.EmployeeMapperDynamic">
    <select id="getEmpsByConditionIf" resultType="com.xz.bean.Employee">
        select * from Employee
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
            <if test="gender==0 or gender=1">
                and gender=#{gender}
            </if>
            <if test="email!=null &amp;&amp; email.trim()!=&quot;&quot;">
                and email=#{email}
            </if>
            <if test="lastName!=null">
                and last_name like #{lastName};
            </if>
        </where>
    </select>

    <select id="getEmpsByConditionTrim" resultType="com.xz.bean.Employee">
        select * from Employee
        <trim prefix="where" suffixOverrides="and">
            <if test="id!=null">
                id=#{id} and
            </if>
            <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
                last_name like #{lastName} and
            </if>
            <if test="email!=null and email.trim()!=&quot;&quot;">
                email=#{email} and
            </if>
            <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
            <if test="gender==0 or gender==1">
                gender=#{gender}
            </if>
        </trim>
    </select>

    <select id="getEmpsByConditionChoose" resultType="com.xz.bean.Employee">
        select * from Employee
        <where>
            <choose>
                <when test="id>3">
                    id=#{id}
                </when>
                <when test="lastName!=null">
                    last_name=#{lastName}
                </when>
                <otherwise>
                    id=1;
                </otherwise>
            </choose>
        </where>
    </select>

    <update id="updateEmp">
        update Employee
        <set>
            <if test="lastName!=null">
                last_name=#{lastName},
            </if>
            <if test="email!=null">
                email=#{email},
            </if>
            <if test="gender!=null">
                gender=#{gender},
            </if>
            <if test="department!=null">
                d_id=#{department.id}
            </if>
        </set>
        where id=#{id};
    </update>

    <select id="getEmpsByConditionForeach" resultType="com.xz.bean.Employee">
        select * from Employee
        <foreach collection="ids" item="item_id" separator="," open="where id in (" close=")">
            #{item_id}
        </foreach>
    </select>

    <insert id="addEmps">
        insert into Employee(<include refid="insertColumn"/>) values
        <foreach collection="emps" item="emp" separator=",">
            (#{emp.lastName},#{emp.email},#{emp.gender})
        </foreach>
    </insert>

    <sql id="insertColumn">
        last_name,email,gender
    </sql>
</mapper>

6.1 if&where

:判断。

test:设置判断条件,遇见特殊符号应该去写转义字符。

:相当于直接在sql后面加where的自动优化方法

<!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
<!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
<select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
    select * from tbl_employee
    <!-- where -->
    <where>
        <!-- test:判断表达式(OGNL)
        OGNL参照PPT或者官方文档。
               c:if  test
        从参数中取值进行判断
        遇见特殊符号应该去写转义字符:
        &&:
        -->
        <if test="id!=null">
            id=#{id}
        </if>
        <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
            and last_name like #{lastName}
        </if>
        <if test="email!=null and email.trim()!=&quot;&quot;">
            and email=#{email}
        </if>
        <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
        <if test="gender==0 or gender==1">
            and gender=#{gender}
        </if>
    </where>
</select>

6.2 trim

trim可以替代where,是一种更全面的字符拼串方式。

后面多出的and或者or where标签不能解决
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符

<!--public List<Employee> getEmpsByConditionTrim(Employee employee);  -->
<select id="getEmpsByConditionTrim" resultType="com.atguigu.mybatis.bean.Employee">
    select * from tbl_employee
    <!-- 后面多出的and或者or where标签不能解决
    prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
            prefix给拼串后的整个字符串加一个前缀
    prefixOverrides="":
            前缀覆盖: 去掉整个字符串前面多余的字符
    suffix="":后缀
            suffix给拼串后的整个字符串加一个后缀
    suffixOverrides=""
            后缀覆盖:去掉整个字符串后面多余的字符
    -->
    <!-- 自定义字符串的截取规则 -->
    <trim prefix="where" suffixOverrides="and">
        <if test="id!=null">
            id=#{id} and
        </if>
        <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
            last_name like #{lastName} and
        </if>
        <if test="email!=null and email.trim()!=&quot;&quot;">
            email=#{email} and
        </if>
        <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
        <if test="gender==0 or gender==1">
            gender=#{gender}
        </if>
    </trim>
</select>

6.3 choose

相当于java语句中的case,只会选择一个满足条件的进行匹配。

when:是choose的查询条件,相当于前面说的if

<!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
<select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.bean.Employee">
    select * from tbl_employee
    <where>
        <!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个 -->
        <choose>
            <when test="id!=null">
                id=#{id}
            </when>
            <when test="lastName!=null">
                last_name like #{lastName}
            </when>
            <when test="email!=null">
                email = #{email}
            </when>
            <otherwise>
                gender = 0
            </otherwise>
        </choose>
    </where>
</select>

6.3 set

在更新语句中使用,使用方式和前面的where一样,可以用trim代替

<!--public void updateEmp(Employee employee);  -->
<update id="updateEmp">
    <!-- Set标签的使用 -->
    update tbl_employee
    <set>
        <if test="lastName!=null">
            last_name=#{lastName},
        </if>
        <if test="email!=null">
            email=#{email},
        </if>
        <if test="gender!=null">
            gender=#{gender}
        </if>
    </set>
    where id=#{id}
</update>

使用trim代替:

<trim prefix="set" suffixOverrides=",">
    <if test="lastName!=null">
        last_name=#{lastName},
    </if>
    <if test="email!=null">
        email=#{email},
    </if>
    <if test="gender!=null">
        gender=#{gender}
    </if>
</trim>
where id=#{id}

6.4 foreach

collection:指定要遍历的集合:
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list的时候是index就是索引,item就是当前值
遍历map的时候index表示的就是map的key,item就是map的值

​ #{变量名}就能取出变量的值也就是当前遍历出的元素

<!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids);  -->
<select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
    select * from tbl_employee
    <foreach collection="ids" item="item_id" separator=","
             open="where id in(" close=")">
        #{item_id}
    </foreach>
</select>

第二种实例:

<!-- 批量保存 -->
<!--public void addEmps(@Param("emps")List<Employee> emps);  -->
<!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
<insert id="addEmps">
    insert into tbl_employee(
    <include refid="insertColumn"></include>
    )
    values
    <foreach collection="emps" item="emp" separator=",">
        (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
    </foreach>
</insert><!--   -->

6.5 sql

抽取可重用的sql片段。方便后面引用
1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
2、include来引用已经抽取的sql:
3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
include-property:取值的正确方式${prop},
#{不能使用这种方式}

抽取sql:

<sql id="insertColumn">
    <if test="_databaseId=='oracle'">
        employee_id,last_name,email
    </if>
    <if test="_databaseId=='mysql'">
        last_name,email,gender,d_id
    </if>
</sql>

include使用sql:

<insert id="addEmps">
    insert into Employee(<include refid="insertColumn"/>) values
    <foreach collection="emps" item="emp" separator=",">
        (#{emp.lastName},#{emp.email},#{emp.gender})
    </foreach>
</insert>

6.6 两个内置参数

两个内置参数:
不只是方法传递过来的参数可以被用来判断,取值。。。
mybatis默认还有两个内置参数:
_parameter:代表整个参数
单个参数:_parameter就是这个参数
多个参数:参数会被封装为一个map;_parameter就是代表这个map

​ _databaseId:如果配置了databaseIdProvider标签。
​ _databaseId就是代表当前数据库的别名oracle

<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
<select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
    <!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
    <bind name="_lastName" value="'%'+lastName+'%'"/>
    <if test="_databaseId=='mysql'">
        select * from tbl_employee
        <if test="_parameter!=null">
            where last_name like #{lastName}
        </if>
    </if>
    <if test="_databaseId=='oracle'">
        select * from employees
        <if test="_parameter!=null">
            where last_name like #{_parameter.lastName}
        </if>
    </if>
</select>

7. 缓存机制

mysql8中已经默认关闭查询缓存了,而如今缓存用的更多的则是redis,这里知道即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值