mybatis

一.MyBatis简介

1原理:

Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。

2.MyBatis的框架核心
1、 mybatis配置文件,包括Mybatis全局配置文件和Mybatis映射文件,其中全局配置文件配置了数据源、事务等信息;映射文件配置了SQL执行相关的信息。
2、 mybatis通过读取配置文件信息(全局配置文件和映射文件),构造出SqlSessionFactory,即会话工厂。
3、 通过SqlSessionFactory,可以创建SqlSession即会话。Mybatis是通过SqlSession来操作数据库的。
4、 SqlSession本身不能直接操作数据库,它是通过底层的Executor执行器接口来操作数据库的。Executor接口有两个实现类,一个是普通执行器,一个是缓存执行器(默认)。
5、 Executor执行器要处理的SQL信息是封装到一个底层对象MappedStatement中。该对象包括:SQL语句、输入参数映射信息、输出结果集映射信息。其中输入参数和输出结果的映射类型包括HashMap集合对象、POJO对象类型。

二.Mybatis入门

1.导包

mybatis-3.5.0/lib下所有包
mybatis-3.5.0.jar
mysql-connector-java-5.1.37-bin.jar

2.在classpath下创建log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### direct messages to file mylog.log ###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=/home/miracle/Desktop/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

### set log levels - for more verbose logging change 'info' to 'debug' ###

log4j.rootLogger=debug, stdout
3.编写javaBean

User

package com.miracle.model;

import java.util.Date;

public class User {

    private int id;
    private String username;
    private String sex;
    private Date birthday;
    private String address;

    public User() {

    }

    public User(String username, String sex, Date birthday, String address) {
        this.username = username;
        this.sex = sex;
        this.birthday = birthday;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                ", address='" + address + '\'' +
                '}';
    }
}
4.创建SqlMapConfig.xml(mybatis全局配置文件)
<?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>
    <!-- 加载classpath下的配置文件
     不建议使用 配置数据源时候 用${key} 取值时,会和sql映射文件中的${key}冲突的bug
     -->
    <!--<properties resource="db.properties"></properties>-->

    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

    <!-- 配置mybatis的环境信息
        environments标签里面可以包含多个environment标签,
        每一个代表一套配置,通过environments中的default属性来指定
    -->
    <environments default="development">
        <environment id="development">
            <!-- 配置JDBC事务控制,由mybatis进行管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源,采用dbcp连接池 -->
            <dataSource type="POOLED">
                <!-- 从properties文件中拿值,不建议使用 -->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 告诉mybatis加载映射文件 -->
    <mappers>
        <mapper resource="com/miracle/orm/User.xml"></mapper>
        <!--这里也可以设置包名,mybatis会自动加载指定包下的所有mapper文件-->
        <!--<package name="com.miracle.mapper"></package>-->
    </mappers>
</configuration>
5.编写映射文件User.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace一般以映射文件的全路径名来命名 -->
<mapper namespace="com.miracle.orm.User">
    <!-- 根据id查询
        [#{}]: 表示一个占位符?
     -->
    <select id="findUserById" parameterType="int" resultType="com.miracle.orm.User">
        select * from user where id = #{id}
    </select>
    <!--
        ${} 表示拼接SQL字符串
        ${value} 表示要拼接的是简单类型参数
        简单类型:int,byte,String...
        1.如果参数为简单类型时,${}里面的参数名称必须是value
		
		$符取值使用场景:比如分表,排序
			select * from ${year}_salary where xxx;
			select * from tbl_employee order by ${f_name} ${order}
     -->
    <select id="findUserByName" parameterType="String" resultType="com.miracle.orm.User">
        select * from user where username like '%${value}%'
    </select>

    <!-- 插入数据
        这里的站位是写javaBean的属性
     -->
    <insert id="insertUser" parameterType="com.miracle.orm.User">
        <!--
            selectKey标签:通过这个标签来返回插入数据的主键,
                          实际原理是执行插入语句后,又调用了一次查询,将查询的主键赋值到返回值中
            keyProperty:指定javaBean中用来接收主键的字段
            resultType:生成主键所对应的java类型
            last_insert_id:mysql的函数,用于当插入一条数据后 执行此函数可以返回刚才插入记录的主键值
            order:指定该查询主键SQL语句的执行顺序,相对于insert语句,由上面可知 这里写AFTER
         -->
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            select last_insert_id()
        </selectKey>
        insert into user (username, sex, birthday, address)
        value
        (#{username}, #{sex}, #{birthday}, #{address})
    </insert>

    <!-- 删除
     -->
    <delete id="deleteUser" parameterType="int">
        delete from user where id = #{id}
    </delete>

    <!-- 更新
    -->
    <update id="updateUser" parameterType="com.miracle.orm.User">
        update user set address = #{address}, sex = #{sex}
        where id = #{id}
    </update>
</mapper>
6.编写测试类
package com.miracle.test;

import com.miracle.orm.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

/**
 * 普通方式
 */
public class Demo {

    private SqlSession sqlSession;

    /**
     * 获取session
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
        // 1.读取配置文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        sqlSession = sqlSessionFactory.openSession();
    }

    /**
     * 提交事务
     */
    @After
    public void destory(){
        sqlSession.commit();
        sqlSession.close();
    }
    /**
     * 查询
     */
    @Test
    public void test1(){
                                                 // 这里写xml映射文件的 namespace + id
        User user = (User) sqlSession.selectOne("com.miracle.orm.User.findUserById", 10);
        System.out.println(user);
        List<User> userList = sqlSession.selectList("com.miracle.orm.User.findUserByName", "张");
        System.out.println(userList);
    }

    /**
     * 插入
     */
    @Test
    public void test2(){
        User user = new User("gyf2", "1", new Date(), "广州");
        // 返回受影响的行数
        int affectRow = sqlSession.insert("com.miracle.orm.User.insertUser", user);
        System.out.println(affectRow);
    }

    /**
     * 删除
     */
    @Test
    public void test3(){
        // 返回受影响的行数
        int affectRow = sqlSession.delete("com.miracle.orm.User.deleteUser", 33);
        System.out.println(affectRow);
    }

    /**
     * 更新
     */
    @Test
    public void test4(){
        User user = new User();
        user.setId(27);
        user.setSex("男");
        user.setAddress("深圳");
        // 返回受影响的行数
        int affectRow = sqlSession.update("com.miracle.orm.User.updateUser", user);
        System.out.println(affectRow);
    }

    /**
     * 插入后获取插入数据的id,设置到JavaBean中
     */
    @Test
    public void test5(){
        User user = new User("gyf3", "2", new Date(), "广州");
        // 返回受影响的行数
        int affectRow = sqlSession.insert("com.miracle.orm.User.insertUser", user);
        System.out.println(affectRow);
        // 返回插入数据的id
        int id = user.getId();
        System.out.println(id);
    }
}

三.MyBatis编写Dao层【mapper代理方式实现】

1.概述

Mapper代理的开发方式,程序员只需要编写mapper接口(相当于dao接口)即可。Mybatis会自动的为mapper接口生成动态代理实现类。
不过要实现mapper代理的开发方式,需要遵循一些开发规范。

1. mapper接口的全限定名要和mapper映射文件的namespace的值相同。
2. mapper接口的方法名称要和mapper映射文件中的statement的id相同;
3. mapper接口的方法参数只能有一个,且类型要和mapper映射文件中statement的parameterType的值保持一致。
4. mapper接口的返回值类型要和mapper映射文件中statement的resultType值或resultMap中的type值保持一致;
2.demo

编写mapper接口:UserMapper

package com.miracle.mapper;

import com.miracle.model.User;
import com.miracle.vo.UserQueryVo;
import java.util.List;
import java.util.Map;

public interface UserMapper {
    /*
      有时候去数据库查询一条记录多个列,
      这是没有对应业务的JavaBean对象,
      可以把单条查询结果封装到map中,
      以列名为key,列值为value
     */
    public Map<String, Object> getEmpByIdReturnMap(Integer id);
    
    /**
     * @param user
     * @return  受影响的行数
     */
    // 使用mapper方式开发,那么接口方法的参数只能接收一个参数
    public int save(User user);

    public User findUserById(int id);

    public List<User> findUserByUserQueryVo(UserQueryVo userQueryVo);

    public List<User> findUserListByMap(Map<String, Object> map);

    public int findUserCount(UserQueryVo userQueryVo);

    public User findUserByIdResultMap(int id);

    public List<User> findUserList(UserQueryVo userQueryVo);

    public List<User> findUserByIds(UserQueryVo userQueryVo);

    public List<User> findUserByIds2(List<Integer> ids);
    /*
       mybatis 增删改 在接口放回方法处
       允许将返回值 void 改为:
       Integer:表示影响行数
       Long:表示影响行数
       Boolean:影响行数超过一,返回true,否则false
    */
    public Long addEmp(Employee employee);

    public Long updateEmp(Employee employee);

    public Boolean deleteEmpById(Integer id);
}

编写xml映射文件:UserMapper.xml

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

<!-- namespace内容为mapper接口的全路径名 -->
<mapper namespace="com.miracle.mapper.UserMapper">
    <select id="getEmpByIdReturnMap" resultType="map">
        select * from tbl_employee where id != #{id}
    </select>
    
    <!-- id要和接口方法名一样 -->
    <insert id="save" parameterType="com.miracle.model.User">
        insert into user (username, sex, birthday, address)
        value (#{username}, #{sex}, #{birthday}, #{address})
    </insert>

    <select id="findUserById" parameterType="int" resultType="com.miracle.model.User">
      select * from user where id = #{id}
    </select>

    <!-- 通过包装类查数据 -->
    <select id="findUserByUserQueryVo" parameterType="com.miracle.vo.UserQueryVo" resultType="com.miracle.model.User">
      select u.*
      from user u
      where u.id <![CDATA[<>]]> #{user.id}
    </select>

    <!-- 通过Map查询数据 -->
    <select id="findUserListByMap" parameterType="hashmap" resultType="com.miracle.model.User">
      select u.* from user u where u.username like '%${user}%' and u.sex = #{sex}
    </select>

    <!-- 聚合函数查询用户个数 -->
    <select id="findUserCount" parameterType="com.miracle.vo.UserQueryVo" resultType="int">
        select count(*) from user where sex=#{user.sex}
    </select>

    <!-- 设置返回数据为resultMap类型的示例 -->
    <resultMap id="userResultMap" type="com.miracle.model.User">
        <id property="id" column="id_"></id>
        <result property="username" column="username_"></result>
        <result property="sex" column="sex_"></result>
        <result property="birthday" column="birthday_"></result>
        <result property="address" column="addresss_"></result>
    </resultMap>
    <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
       select id id_, username username_, sex sex_, birthday birthday_, address addresss_
       from user
       where id = #{id};
    </select>

    <!-- 声明一个SQL片段 -->
    <sql id="select_user_where">
        <if test="user != null">
            <if test="user.sex != null and user.sex != ''">
                sex = #{user.sex}
            </if>
            <if test="user.username != null and user.username != ''">
                and username like '%${user.username}%'
            </if>
        </if>
    </sql>
    <!-- if和where标签 -->
    <select id="findUserList" parameterType="com.miracle.vo.UserQueryVo" resultType="com.miracle.model.User">
      select * from user
      <!-- 条件判断 -->
      <!-- Where标签:会去掉条件中的第一个and符号。 -->
      <where>
          <!-- 引用SQL片段 -->
          <include refid="select_user_where"></include>
      </where>
    </select>

    <!-- foreach标签使用 遍历JavaBean中的集合 -->
    <select id="findUserByIds" parameterType="com.miracle.vo.UserQueryVo" resultType="com.miracle.model.User">
        select * from user
        <where>
            <!-- 判断列表ids不为空 -->
            <if test="ids != null and ids.size > 0">
                <!--
                 collection:要遍历的属性
                 item:遍历出来属性的名字
                 open:拼接sql开始部分
                 separator:拼接sql中间部分
                 close:拼接sql结束部分
                 -->
                <foreach collection="ids" item="id" open="id in (" close=")" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

    <!-- foreach标签使用 直接遍历 集合 -->
    <select id="findUserByIds2" parameterType="list" resultType="com.miracle.model.User">
        select * from user
        <where>
            <!-- 判断列表ids不为空,注意这里不能写ids 要写list -->
            <if test="list != null and list.size > 0">
                <!--
                 collection:要遍历的属性
                 item:遍历出来属性的名字
                 open:拼接sql开始部分
                 separator:拼接sql中间部分
                 close:拼接sql结束部分
                 -->
                <foreach collection="list" item="id" open="id in (" close=")" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>

    <insert id="addEmp" parameterType="com.mybatis.beans.Employee">
        insert into tbl_employee(last_name, email, gender) values (
            #{lastName},#{email},#{gender}
        )
    </insert>

    <update id="updateEmp">
        update tbl_employee
        set last_name = #{lastName},
            email = #{email},
            gender = #{gender}
        where id = #{id}
    </update>

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

编写测试

package com.miracle.test;

import com.miracle.mapper.UserMapper;
import com.miracle.model.User;
import com.miracle.vo.UserQueryVo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * mapper代理方式,mapper就相当于dao,用mapper开发就不需要dao了,service层直接调用mapper
 */
@SuppressWarnings("all")
public class Demo {
    private SqlSession sqlSession;
    private UserMapper userMapper;

    /**
     * 获取session
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
        // 1.读取配置文件
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        sqlSession = sqlSessionFactory.openSession();
        // 获取mapper
        userMapper = sqlSession.getMapper(UserMapper.class);
    }

    /**
     * 提交事务
     */
    @After
    public void destory(){
        sqlSession.commit();
        sqlSession.close();
    }

    /**
     * 查询
     */
    @Test
    public void test1(){
        // 查询
        User user = userMapper.findUserById(1);
        System.out.println(user);
    }

    /**
     * 保存
     */
    @Test
    public void test2(){
        // 保存
        User user = new User("王五", "x", new Date(), "xx");
        userMapper.save(user);
    }

    /**
     * 复杂类型查询
     */
    @Test
    public void test3(){
        User user = new User();
        user.setId(1);
        UserQueryVo userQueryVo = new UserQueryVo();
        userQueryVo.setUser(user);
        List<User> userList = userMapper.findUserByUserQueryVo(userQueryVo);
        System.out.println(userList);
    }

    /**
     * map类型查询
     */
    @Test
    public void test4(){
        Map<String, Object> map = new HashMap<>();
        map.put("user", "张");
        map.put("sex", 1);
        List<User> userList = userMapper.findUserListByMap(map);
        System.out.println(userList);
    }

    @Test
    public void test5(){
        UserQueryVo userQueryVo = new UserQueryVo();
        User user = new User();
        user.setSex("2");
        userQueryVo.setUser(user);
        int count = userMapper.findUserCount(userQueryVo);
        System.out.println(count);
    }

    @Test
    public void test6(){
        User user = userMapper.findUserByIdResultMap(1);
        System.out.println(user);
    }

    @Test
    public void test7(){
        User user = new User();
        user.setUsername("张");
        user.setSex("1");
        UserQueryVo userQueryVo = new UserQueryVo();
        userQueryVo.setUser(user);
        List<User> userList = userMapper.findUserList(userQueryVo);
        System.out.println(userList);
    }

    /**
     * foreach 遍历JavaBean中的list
     */
    @Test
    public void test8(){
        List<Integer> ids = new ArrayList<>();
        ids.add(10);
        ids.add(16);
        ids.add(22);
        ids.add(24);
        UserQueryVo userQueryVo = new UserQueryVo();
        userQueryVo.setIds(ids);
        List<User> userList = userMapper.findUserByIds(userQueryVo);
        System.out.println(userList);
    }

    /**
     * foreach 遍历list
     */
    @Test
    public void test9(){
        List<Integer> ids = new ArrayList<>();
        ids.add(10);
        ids.add(16);
        ids.add(22);
        ids.add(24);
        List<User> userList = userMapper.findUserByIds2(ids);
        System.out.println(userList);
    }
}

四.mybatis全局配置文件介绍

  • 注意mybatis全局配置文件标签书写是有顺序的

properties

settings

typeAliases

typeHandlers

objectFactory

objectWrapperFactory

plugins

environments?

databaseIdProvider

mappers

1.<environments>标签介绍

<configuration>
    <!-- 配置mybatis的环境信息
        environments标签里面可以包含多个environment标签,
        每一个代表一套配置,通过environments中的default属性来指定,使用那一套环境
    -->
    <environments default="development">
        <environment id="development">
            <!-- 配置JDBC事务控制,由mybatis进行管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源,采用dbcp连接池 -->
            <dataSource type="POOLED">
                <!-- 从properties文件中拿值,不建议使用 -->
                <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>
</configuration>

2.<properties>标签介绍

mybatis可以使用properties来引入外部properties配置文件的内容

<configuration>
    <!--
        properties标签有两个属性:
            1.resource:引入类路径下的资源
            2.url:引入网络路径或者磁盘路径下的资源
     -->
    <properties resource="dbconfig.properties"></properties>
	
	<!-- 配置mybatis的环境信息
        environments标签里面可以包含多个environment标签,
        每一个代表一套配置,通过environments中的default属性来指定
    -->
    <environments default="development">
        <environment id="development">
            <!-- 配置JDBC事务控制,由mybatis进行管理 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源,采用dbcp连接池 -->
            <dataSource type="POOLED">
                <!-- 从properties文件中拿值,不建议使用 -->
                <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>
</configuration>

3.<settings>标签介绍

<configuration>
	<!--
	    settings包含很多重要的设置项
	    setting:用来设置每一个设置项
	        name:设置项名
	        value:设置项取值
	-->
	<settings>
	    <!-- 打印查询语句 -->
	    <setting name="logImpl" value="STDOUT_LOGGING" />
	    <!--
            如果把javaBean对象的Null字段 插入到oracle中
            oracle无法识别,这里可以配置如下内容(影响全局)
            也可以在mapper映射文件中的sql里面,指定某个可能
            为空字段的jdbcType=NULL
            #{email,jdbcType=NULL}
         -->
        <setting name="jdbcTypeForNull" value="NULL"/>
        <!--懒加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
	</settings>
</configuration>

4.<mappers>标签介绍

<configuration>
    <!-- 告诉mybatis加载映射文件,将sql映射文件出册到全局配置中 -->
    <mappers>
        <!--注册classpath下的sql映射文件-->
        <mapper resource="com/miracle/orm/User.xml"></mapper>
        <!--这里也可以设置包名,mybatis会自动加载指定包下的所有mapper文件-->
        <!--<package name="com.miracle.mapper"></package>-->
    </mappers>
</configuration>

五.mybatisSQL映射文件编写

1.select标签 属性

在这里插入图片描述

2.mapper 映射文件中 #{} 和 ${} 区别

1.#{} 和 ${} 区别

#{}:相当于预处理中的占位符?。(底层是JDBC的preparedstatement)
	#{}里面的参数表示接收java输入参数的名称。
	#{}可以接受HashMap、POJO类型的参数。
	当接受简单类型的参数时,#{}里面可以是value,也可以是其他。
	#{}可以防止SQL注入。
使用场景:
	尽量用#{}取值



${}:相当于拼接SQL串,对传入的值不做任何解释的原样输出。(底层是JDBC的statement)
	${}会引起SQL注入,所以要谨慎使用。
	${}可以接受HashMap、POJO类型的参数。
	当接受简单类型的参数时,${}里面只能是value。
使用场景:
	比如分表,排序... 按照年份分表拆分:
	select * from ${year}_salary whrere xxx
	select * from tbl_employee order by ${f_name} ${asc}

六.动态SQL

1.If标签

If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。
注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’;

eg:见下图

2.where标签

会去掉条件中的第一个and符号。

eg:见下图

3.choose 分支
<select id="getEmpsByConditionChoose" resultType="com.mybatis.beans.Employee">
    select * from tbl_employee
    <where>
        <!-- 如果查询对象id有值就按照id查,
            如果lastName有值就按照lastName查,
            否则查询所有
            类似java中的switch case
         -->
        <choose>
            <when test="id != null and id != ''">
                id = #{id}
            </when>
            <when test="lastName != null and lastName != ''">
                last_name = #{lastName}
            </when>
            <otherwise>
                1 = 1
            </otherwise>
        </choose>
    </where>
</select>
4.set 封装修改条件

需求:
想根据JavaBean更新数据库记录,当JavaBean字段非空则更新响应字段,空则不更新

<update id="updateEmp">
    update tbl_employee
    set
    <if test="lastName != null and lastName != ''">
        last_name = #{lastName},
    </if>
    <if test="email != null and email != ''">
        email = #{email},
    </if>
    <if test="gender != null and gender != ''">
        gender = #{gender}
    </if>
    where id = #{id}
</update>

但是这个sql执行会有问题,if标签里面的sql后面有个逗号,无法处理,这是要用到set标签

<update id="updateEmp">
    update tbl_employee
    <set>
        <if test="lastName != null and lastName != ''">
            last_name = #{lastName},
        </if>
        <if test="email != null and email != ''">
            email = #{email},
        </if>
        <if test="gender != null and gender != ''">
            gender = #{gender}
        </if>
    </set>
    where id = #{id}
</update>
5.foreach 遍历
<select id="getEmpsByConditionForeach" resultType="com.mybatis.beans.Employee">
    select * from tbl_employee where id in
    <!--
        collection: 指定要遍历的集合(必须为list或者collection )
        item:将遍历出的元素赋值给指定的变量
        separator:表示每个元素之间的分隔符
        open:遍历出所有结果拼接出一个开始的字符
        close:遍历出所有结果拼接出一个结束的字符
        index:索引,
                如果遍历list的时候,index就是索引
                如果遍历map的时候,index就是map的key
    -->
    <foreach collection="list" item="item_id" separator="," open="(" close=")">
        #{item_id}
    </foreach>
</select>
5.trim
<insert id="insertDepartment" parameterType="com.miracle.beans.Department">
    insert into tbl_dept
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="deptId != null and deptId != ''">
            dept_id,
        </if>
        <if test="deptName != null and deptName != ''">
            dept_name,
        </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
        <if test="deptId != null and deptId != ''">
            #{deptId,jdbcType=INTEGER},
        </if>
        <if test="deptName != null and deptName != ''">
            #{deptName,jdbcType=VARCHAR},
        </if>
    </trim>
</insert>

五.SQL片断

Mybatis提供了SQL片段的功能,可以提高SQL的可重用性。
在这里插入图片描述

六.总结

2.selectOne和selectList
selectOne:只能查询0或1条记录,大于1条记录的话,会报错:
selectList:可以查询0或N条记录

3.mybatis特殊字符处理
使用<![CDATA[ ]]>符号进行说明,在最里层的[ ]里面内容不进行解析

4.输出映射 resultType/resultMap
(1)resultType
使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功。
如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象;
如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象。

输出单个pojo对象和pojo列表时,mapper映射文件中的resultType的类型是一样的,mapper接口的方法返回值不同。同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,会根据返回值的类型,决定调用selectOne方法还是selectList方法。

(2)resultMap(当mybatis返回JavaBean嵌套JavaBean时,向内层JavaBean里面设置值可以用resultMap)
如果查询出来的列名和属性名不一致,通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。
1、 定义resultMap
2、使用resultMap作为statement的输出映射类型

(3)总结
resultType:将查询结果按照sql列名pojo属性名一致性映射到pojo中。
resultMap:使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
association:将关联查询信息映射到一个pojo对象中。
collection:将关联查询信息映射到一个list集合中。

5.mybatis标签大全
https://blog.csdn.net/weixin_40950778/article/details/78655288

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值