一篇文章让你瞬间知道Mybatis框架是如何使用的

mybatis概述

mybatis简介

MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。

MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录.

mybatis历史

原是apache的一个开源项目iBatis, 2010年6月这个项目由apache software foundation 迁移到了google code,随着开发团队转投Google Code旗下,ibatis3.x正式更名为Mybatis ,代码于2013年11月迁移到Github(下载地址见后)。

iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)

为什么要使用mybatis。

MyBatis是一个半自动化的持久化层框架。

jdbc编程—当我们使用jdbc持久化的时候,sql语句被硬编码到java代码中。这样耦合度太高。代码不易于维护。在实际项目开发中会经常添加sql或者修改sql,这样我们就只能到java代码中去修改。

Hibernate和JPA
长而又难又复杂SQL,对于Hibernate而言处理也不容易
内部自动生产的SQL,不容易做特殊优化。
基于全映射的全自动框架,javaBean存在大量字段时无法只映射部分字段。导致数据库性能下降。

对开发人员而言,核心sql还是需要自己优化
sql和java编码分开,功能边界清晰,一个专注业务、一个专注数据。
可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO映射成数据库中的记录。成为业务代码+底层数据库的媒介

mybatis的Hello 示例程序

  • 创建一个数据库和一个单表
drop database if exists mybatis;

create database mybatis;

use mybatis;
##############################################################################
################################### 单表 ######################################
##############################################################################
## 创建单表
create table t_user(
	`id` int primary key auto_increment,
	`last_name`	varchar(50),
	`sex` int
);

insert into t_user(`last_name`,`sex`) values('wzg168',1);

select * from t_user;
  • Mybatis程序示例:
    1 先编写数据库表对应的User对象
public class User {
    private Integer id;
    private String lastName;
    private Integer sex;

2 编写mybatis的核心配置文件 : mybatis-config.xml ( 放在src目录下 )

<?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>
    <!-- environments是配置数据库连接属性 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--修改数据库的连接属性-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
        我们说,mybatis是把sql语句配置到xml配置文件中
        告诉mbyatis到哪里去加载sql语句的配置文件
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers> -->
</configuration>

测试的代码:

package com.atguigu.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class MybatisHelloTest {

    @Test
    public void test() throws IOException {
        // 从 XML 中构建 SqlSessionFactory
        // 读取mybatis的核心配置文件
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        // 通过sqlSessionFactoryBuilder创建SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        System.out.println(sqlSessionFactory);
    }

}

3 编写Mapper接口 ( DAO接口一样 )
JavaBean名    Mapper接口命名习惯( 不需要自己实现 )   Dao命名 ( 需要自己实现 )
User   UserMapper    UserDao
Book     BookMapper    BookDao

在 mybatis中我们需要为Mapper接口编写mapper接口的方法中执行的sql语句的配置文件.

JavaBean名    Mapper接口名     sql配置文件名
User    UserMapper     UserMapper.xml
Book    BookMapper     BoookMapper.xml

Mapper.xml和Mapper接口一般都是放在同一个包下

Mapper接口:

public interface UserMapper {

    // mybatis的hello world ==>>> 要求我们查询数据库表t_user中id为1的记录
    public User queryUserById(Integer id);
}

Mapper.xml配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    要修改mapper和namespace名称空间属性值
        它的属性值必须是Mapper接口的全类名
-->
<mapper namespace="com.atguigu.mapper.UserMapper">
    <!--
        public User queryUserById(Integer id);
        select标签表示配置一个select查询语句
            id 属性值必须是方法名
            parameterType 属性配置方法的参数类型       int 表示 java.lang.Integer类型
            resultType  属性设置方法的返回值类型

        在mybatis中占位符要写成为: #{}
    -->
    <select id="queryUserById" parameterType="int" resultType="com.atguigu.pojo.User">
        select `id`,`last_name` lastName, `sex` from t_user where id = #{id}
    </select>
</mapper>

修改Mybatis-config.xml核心配置文件,加载sql的配置文件:

<?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>
    <!-- environments是配置数据库连接属性 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--修改数据库的连接属性-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
        我们说,mybatis是把sql语句配置到xml配置文件中
        告诉mbyatis到哪里去加载sql语句的配置文件
    -->
    <mappers>
        <!--,去加载UserMapper.xml配置文件 -->
        <mapper resource="com/atguigu/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

测试代码:

@Test
public void test2() throws IOException {
    // 创建SqlSessionFactory对象
    InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    // SqlSession相当于Jdbc中的Connection连接对象
    SqlSession session = sqlSessionFactory.openSession();
    try {
        // 获取UserMapper的实现类
        UserMapper userMapper = session.getMapper(UserMapper.class);

        User user = userMapper.queryUserById(1);

        System.out.println(user);
    } finally {
        session.close();
    }
}

给mybatis添加日记操作:
先添加日记的jar包
junit_4.12.jar
log4j-1.2.17.jar
mybatis-3.5.1.jar
mysql-connector-java-5.1.7-bin.jar
org.hamcrest.core_1.3.0.jar
在src目录下,配置日记功能的配置文件. log4j.properties

# 全局日志配置
log4j.rootLogger=DEBUG, stdout
# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
  • Mapper接口的CRUD实现
    Mapper接口:
public interface UserMapper {
    // mybatis的hello world ==>>> 要求我们查询数据库表t_user中id为1的记录
    public User queryUserById(Integer id);

    public List<User> queryUsers();

    public int saveUser(User user);

    public int deleteUserById(Integer id);

    public int updateUserById(User user);
}

Mapper.xml配置文件 :

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
    要修改mapper和namespace名称空间属性值
        它的属性值必须是Mapper接口的全类名
-->
<mapper namespace="com.atguigu.mapper.UserMapper">
    <!--
        public User queryUserById(Integer id);
        select标签表示配置一个select查询语句
            id 属性值必须是方法名
            parameterType 属性配置方法的参数类型       int 表示 java.lang.Integer类型
            resultType  属性设置方法的返回值类型

        在mybatis中占位符要写成为: #{}
    -->
    <select id="queryUserById" resultType="com.atguigu.pojo.User">
        select `id`,`last_name` lastName, `sex` from t_user where id = #{id}
    </select>


<!--    public List<User> queryUsers();
        resultType 属性设置查询回来的结果每一行转换成为什么具体的类型
-->
    <select id="queryUsers" resultType="com.atguigu.pojo.User">
        select `id`,`last_name` lastName, `sex` from t_user
    </select>


<!--    public int saveUser(User user);
        insert语句配insert标签
        update语句配update标签
        delete语句配delete标签
        select语句配select标签
-->
    <insert id="saveUser" parameterType="com.atguigu.pojo.User">
        insert into t_user( `last_name`,`sex` ) values(#{lastName},#{sex})
    </insert>

<!--    public int deleteUserById(Integer id);-->
    <delete id="deleteUserById" >
        delete from t_user where id = #{id}
    </delete>

<!--    public int updateUserById(User user);-->
    <update id="updateUserById" parameterType="com.atguigu.pojo.User">
        update
            t_user
        set
            `last_name` = #{lastName} ,
            `sex` = #{sex}
        where
            id = #{id}
    </update>
</mapper>

Mapper接口测试

package com.atguigu.test;

import com.atguigu.mapper.UserMapper;
import com.atguigu.pojo.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.BeforeClass;
import org.junit.Test;

import java.io.IOException;

public class UserMapperTest {

    static SqlSessionFactory sqlSessionFactory;

    /**
     * @BeforeClass注解要标识在static的方法上,它会在测试方法执行之前执行,做一些初始化工作. <br/>
     * @BeforeClass 属于junit4测试类
     */
    @BeforeClass
    public static void init() throws IOException {
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml") );
    }

    @Test
    public void queryUserById() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            User user = mapper.queryUserById(1);
            System.out.println(user);
        } finally {
            sqlSession.close();
        }

    }


    @Test
    public void queryUsers() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            UserMapper mapper = session.getMapper(UserMapper.class);

            mapper.queryUsers().forEach(System.out::println);

        } finally {
            session.close();
        }
    }

    @Test
    public void saveUser() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            UserMapper mapper = session.getMapper(UserMapper.class);

            int i = mapper.saveUser(new User(null, "ccccccc", 1));

            System.out.println(i);

            session.commit();//手动提交事务,否则事务就默认回滚
        } finally {
            session.close();
        }
    }

    @Test
    public void deleteUserById() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            UserMapper userMapper = session.getMapper(UserMapper.class);

            userMapper.deleteUserById(5);

            // 写操作,都需要手动提交事务
            session.commit();

        } finally {
            session.close();
        }
    }

    @Test
    public void updateUserById() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            UserMapper userMapper = session.getMapper(UserMapper.class);

            userMapper.updateUserById(new User(4,"oomm", 0));

            session.commit();
        } finally {
            session.close();
        }
    }
}

使用Mapper接口开发需要注意的四个点:
1 Mapper.xml配置文件的名称空间值必须是Mapper接口的全类名
2 Mapper.xml配置文件中的id值必须是Mapper接口的方法名
3 Mapper.xml配置文件文件中参数的类型parameterType必须和Mapper接口的参数类型一致( parameterType参数可选 )
4 Mapper.xml配置文件中返回值类型resultType必须和Mapper接口的返回值类型一致

插入记录并返回主键

一般在插入数据库数据的时候,经常需要把当前插入的生成的id主键值返回.

<!--    public int saveUser(User user);
        insert语句配insert标签
        update语句配update标签
        delete语句配delete标签
        select语句配select标签

        useGeneratedKeys="true" 使用数据库生成的主键值
        keyProperty="id"        将返回的主键值,注入到哪个属性中
-->
    <insert id="saveUser" useGeneratedKeys="true" keyProperty="id" parameterType="com.atguigu.pojo.User">
        insert into t_user( `last_name`,`sex` ) values(#{lastName},#{sex})
    </insert>

selectKey 标签的使用

selectKey标签可以给当前执行的sql语句再配置另一个查询功能的sql.

<insert id="saveUser" parameterType="com.atguigu.pojo.User">
    <!--
        selectKey标签可以配置一个查询语句
            order设置selectkey中的查询语句的执行顺序
                AFTER   后执行
                Before  先执行
            keyProperty="id"        将返回的主键值,注入到哪个属性中
            resultType="int"        表示返回的数据是什么类型
     -->
    <selectKey order="AFTER" keyProperty="id" resultType="int">
        select last_insert_id()
    </selectKey>
    insert into t_user( `last_name`,`sex` ) values(#{lastName},#{sex})
</insert>

注解@KeyMap的使用。

@KeyMap可以把查询回来的多条记录封装为Map.
map的键是: 就是我们指定的唯一值的列 ( 一般使用主键列 )
map的值是: 每行记录转换的对象

Mapper接口:

/**
 * 1 将查询回来每一行记录都封装为USer对象. <br>
 * 2 按照指定的列做为key保存查询到的数据,封装为Map <br/>
 * @return
 */
@MapKey("id")
public Map<Integer,User>queryUserForMap();

Mapper.xml配置文件:

	<!--    /**
	    * 1 将查询回来每一行记录都封装为USer对象. <br>
	    * 2 按照指定的列做为key保存查询到的数据,封装为Map <br/>
	    * @return
	    */
	    @MapKey("id")
	    public Map<Integer,User>queryUserForMap();
    -->
    <select id="queryUserForMap" resultType="com.atguigu.pojo.User">
        select `id`,`last_name`, `sex` from t_user
    </select>

测试代码:

@Test
public void queryUserForMap() {
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);

        Map<Integer, User> map = userMapper.queryUserForMap();
        System.out.println( map.getClass() );
        for (Map.Entry<Integer, User>entry : map.entrySet()) {
            System.out.println( entry.getKey() + " = " +  entry.getValue());
        }
    } finally {
        session.close();
    }
}

mybatis的核心配置之properties

<?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 resource="jdbc.properties">
        <property name="username" value="root"/>
        <property name="password" value="root"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    </properties>

    <!-- environments是配置数据库连接属性 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--修改数据库的连接属性-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--
        我们说,mybatis是把sql语句配置到xml配置文件中
        告诉mbyatis到哪里去加载sql语句的配置文件
    -->
    <mappers>
        <!--,去加载UserMapper.xml配置文件 -->
        <mapper resource="com/atguigu/mapper/UserMapper.xml"/>
    </mappers>
</configuration>

mybatis的核心配置之settings

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。下表描述了设置中各项的意图、默认值等。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

mybatis的核心配置之typeAliases

<!--配置别名-->
<typeAliases>
    <!--typeAlias配置一个别名
            type是你的具体类型的全类名
            alias 是别名
            <typeAlias type="com.atguigu.pojo.User" alias="user" />
    -->
    <!-- 通过配置包名的方式配置所有JavaBean的别名
            别名到底是啥,怎么用
         默认别名,就是类名,但一般用类名首字母小写居多
     -->
    <package name="com.atguigu.pojo"/>

</typeAliases>

在这里插入图片描述

mybatis的核心配置之typeHandlers

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

mybatis的核心配置之environments

environments 标签用于配置数据库环境,
可以配置多个
SqlSessionFactory是单例的. 一个数据库对应一个SqlSessionFactory对象

environment 标签说明

environment 可以配置一个数据库环境
在这里插入图片描述

transactionManager 标签说明

在这里插入图片描述
事务管理器(transactionManager)
在 MyBatis 中有两种类型的事务管理器(也就是 type="[JDBC|MANAGED]"):
• JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
• MANAGED – 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。然而一些容器并不希望连接被关闭,因此需要将 closeConnection 属性设置为 false 来阻止默认的关闭行为。

dataSource 标签说明

type 属性的值有三种: UNPOOLED 、 POOLED 、 JNDI。自定义(实现DataSourceFactory接口)

dataSource 元素使用标准的 JDBC 数据源接口来配置 JDBC 连接对象的资源。
• 大多数 MyBatis 应用程序会按示例中的例子来配置数据源。虽然数据源配置是可选的,但如果要启用延迟加载特性,就必须配置数据源。
有三种内建的数据源类型(也就是 type="[UNPOOLED|POOLED|JNDI]"):
UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形

mybatis的核心配置之databaseIdProvider

它可以提供多数据库的支持.

MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。 MyBatis 会加载不带 databaseId 属性和带有匹配当前数据库 databaseId 属性的所有语句。

	<databaseIdProvider type="DB_VENDOR">
		<property name="SQL Server" value="sqlserver" />
		<property name="MySQL" value="mysql" />
		<property name="DB2" value="db2" />
		<property name="Oracle" value="oracle" />
	</databaseIdProvider>

databaseId测试

<!--    public List<User> queryUsers();
        resultType 属性设置查询回来的结果每一笔转换成为什么具体的类型
     而不带有 databaseId 属性的它可以用于执行任何数据库
-->
    <select id="queryUsers" resultType="user">
        select `id`,`last_name` lastName, `sex` from t_user
    </select>
    <!--
        带有 databaseId 属性的是只是匹配了当前数据库就会执行的sql
    -->
    <select id="queryUsers" resultType="user" databaseId="oracle">
        select `id`,`last_name` lastName, `sex` from t_user where 1 = 1
    </select>

mybatis的核心配置之Mapper ( 使用最多 )

<!--
    我们说,mybatis是把sql语句配置到xml配置文件中
    告诉mbyatis到哪里去加载sql语句的配置文件
-->
<mappers>
    <!--,去加载UserMapper.xml配置文件 -->
    <!--
        是指从ClassPath类路径下开始搜索配置文件
    <mapper resource="com/atguigu/mapper/UserMapper.xml"/> -->

    <!--
        mapper表示配置搜索sql的配置文件
            class 表示搜索指定接口对应的配置文件

        注意事项:
            1 Mapper接口和Mapper.xml配置文件,必须在同一个包下
            2 Mapper接口文件名和Mapper.xml文件名要一致
       <mapper class="com.atguigu.mapper.UserMapper" />
    -->

    <!--配置按照指定的包名去搜索所有Mapper.xml配置文件-->
    <package name="com.atguigu.mapper"/>

</mappers>

注解配置sql语句

编写一个模块,使用注解去配置方法的sql语句
UserMapper接口:

public interface UserMapper {

    /**
     *  @Insert 配置 insert的sql语句 <br/>
     *  @SelectKey 配置一个查询语句( 主要用于配置一个Select语句,用于查询主键 ) <br>
     *          statement 配置你的sql语句 <br>
     *          before 配置是否是先执行selectKey中语句 <br/>
     *          keyProperty 配置查询回来的Key主键给哪个属性赋值 <br/>
     *          resultType 属性配置返回的主键数据类型
     * @param user
     * @return
     */
    @SelectKey(statement = "select last_insert_id()",before = false, keyProperty = "id",resultType = Integer.class)
    @Insert("insert into t_user(`last_name`,`sex`) values(#{lastName},#{sex})")
    public int saveUser(User user);

    /**
     * @Update 配置 update语句
     * @param user
     * @return
     */
    @Update("update t_user set `last_name` = #{lastName} , `sex` = #{sex} where id = #{id}")
    public int updateUserById(User user);

    /**
     * @Delete 注解 配置 delete 语句
     * @param id
     * @return
     */
    @Delete("delete from t_user where id = #{id}")
    public int deleteUserById(Integer id);

    /**
     *@Select 注解配置 select语句
     * @param id
     * @return
     */
    @Select("select `id`, `last_name` lastName,`sex` from t_user where id = #{id}")
    public User queryUserById(Integer id);

    /**
     * @Select 注解配置 select语句
     * @return
     **/
    @Select("select `id`, `last_name` lastName,`sex` from t_user")
    public List<User> queryUsers();

}

测试的代码:

public class UserMapperTest {
    /**
     * sqlSessionFactory是单例的. 一个数据库只有一个SqlSessionFactory对象实例
     */
    static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init() throws Exception{
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    }

    @Test
    public void saveUser() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            // 获取UserMapper实现类
            UserMapper userMapper = session.getMapper(UserMapper.class);

            User user = new User(null,"ddee" , 1);

            System.out.println(userMapper.saveUser(user));

            System.out.println(user);

            session.commit();
        } finally {
            session.close();
        }
    }

    @Test
    public void updateUserById() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            // 获取UserMapper实现类
            UserMapper userMapper = session.getMapper(UserMapper.class);

            User user = new User(7,"bbj" , 0);

            userMapper.updateUserById(user);

            session.commit();
        } finally {
            session.close();
        }
    }

    @Test
    public void deleteUserById() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            // 获取UserMapper实现类
            UserMapper userMapper = session.getMapper(UserMapper.class);

            User user = new User(7,"bbj" , 0);

            userMapper.deleteUserById(8);

            session.commit();
        } finally {
            session.close();
        }
    }

    @Test
    public void queryUserById() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            // 获取UserMapper实现类
            UserMapper userMapper = session.getMapper(UserMapper.class);

            System.out.println(userMapper.queryUserById(9));

        } finally {
            session.close();
        }
    }

    @Test
    public void queryUsers() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            // 获取UserMapper实现类
            UserMapper userMapper = session.getMapper(UserMapper.class);

            userMapper.queryUsers().forEach(System.out::println);

        } finally {
            session.close();
        }
    }
}

数据库中的自增是不回滚的。
注解方式和xml方式可以共用,但不能同时写。一般来说,简单的SQL语句使用注解方式,复杂的SQL语句使用xml方式。

mybatis的参数传递

参数传递是指如何将mapper接口方法中的参数传递给sql语句的占位符. 简单点说,就是 #{} 里应该写啥

一个普通数据类型

Mapper接口:

public interface UserMapper {
    public User queryUserById(Integer id) ;
}

Mapper.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">
<!--
    namespace名称空间的值要改为对应的Mapper接口的全类名
-->
<mapper namespace="com.atguigu.mapper.UserMapper">

    <!--    public User queryUserById(Integer id);
            当Mapper接口参数是一个普通类型的时候,#{}中可以写任意的内容,
            只是推荐写成为参数名.为了更好的可读性
    -->
    <select id="queryUserById" resultType="com.atguigu.pojo.User">
        select `id`,`last_name` lastName,`sex` from t_user where id = #{id}
    </select>
</mapper>

测试代码:

public class UserMapperTest {

    static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init() throws Exception{
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    }

    @Test
    public void queryUserById() {

        SqlSession session = sqlSessionFactory.openSession();

        try {
            UserMapper userMapper = session.getMapper(UserMapper.class);

            User user = userMapper.queryUserById(1);

            System.out.println(user);

        } finally {
            session.close();
        }
    }
}

多个普通数据类型

Mapper接口:

/**
 * 根据给定的性别和名称查询用户信息 <br/>
 *
 * @Param("name") String name 表示将第一个参数的参数名设置为name.
 *
 * @return
 */
public List<User> queryUsersBySexOrName(String name, Integer sex);

Mapper.xml配置文件:

<!--    /**
    * 根据给定的性别和名称查询用户信息
    * @return
    */
    public List<User> queryUsersBySexOrName(String name,Integer sex);
        resultType属性是指定查询回来的每一行数据转换的具体的类型,

        在传递的参数是多个普通类型的情况下.有两种方案可以传递参数的值到占位符中.
        第一种情况是: (mybatis3.5支持)(mybatis3.4是用0,1来表示的)
            arg0    表示第一个参数
            arg1    表示第二个参数
            ......以此类推
            argN    表示第N+1个参数
        第二种情况是:(推荐使用)
            param1  表示第一个参数
            param2  表示第二个参数
            ......以此类推
            paramN  表示第n个参数
    -->
    <select id="queryUsersBySexOrName" resultType="com.atguigu.pojo.User">
        select
            `id`,`last_name` lastName,`sex`
        from
            t_user
        where
            `last_name` = #{param1} or `sex` = #{param2}
    </select>

测试的代码:

@Test
public void queryUsersBySexOrName(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        userMapper.queryUsersBySexOrName("ccccccc", 1).forEach(System.out::println);
    } finally {
        session.close();
    }
}

@Param注解命名参数

Mapper接口:

/**
 * 根据给定的性别和名称查询用户信息 <br/>
 *
 * @Param("name") String name 表示将第一个参数的参数名设置为name.
 *
 * @return
 */
public List<User> queryUsersBySexOrName(@Param("name") String name, @Param("sex") Integer sex);

Mapper.xml配置文件:

<!--   
      public List<User> queryUsersBySexOrName(@Param("name") String name, @Param("sex") Integer sex);
      如果我们在参数中使用了注解@Param("name") String name,则参数name的值可以通过注解指定的名称来进行传递
      也就是如下:
       @Param("name") String name           =====>>>>>      #{ name }
       @Param("sex") Integer sex            =====>>>>>      #{ sex }
       ....... 以此类推
       @Param("xxxx") Integer sex           =====>>>>>      #{ xxxx }
    -->
    <select id="queryUsersBySexOrName" resultType="com.atguigu.pojo.User">
        select
            `id`,`last_name` lastName,`sex`
        from
            t_user
        where
            `last_name` = #{name} or `sex` = #{sex}
    </select>

传递一个Map对象作为参数(使用极少)

Mapper接口

/**
 * 按照map中给定的name和sex来进行查询用户信息
 * @param paramMap
 * @return
 */
public List<User> queryUsersByMap(Map<String,Object> paramMap);

Mapper.xml配置文件:

<!--    /**
    * 按照map中给定的name和sex来进行查询用户信息
    * @param paramMap
    * @return
    */
    public List<User> queryUsersByMap(Map<String,Object> paramMap);

        如果传递的参数是Map类型,则在#{}中需要写上map的key值表示传递相应key的值到sql的占位符中.
        示例代码:
            UserMapper userMapper = session.getMapper(UserMapper.class);
            Map<String,Object> map = new HashMap<>();
            map.put("name","ccccccc");
            map.put("sex",1);
            userMapper.queryUsersByMap(map).forEach(System.out::println);
        使用如下:
            Map<String,Object> map = new HashMap<>();
            map.put("name","ccccccc");      ====>>>>  #{ name }
            map.put("sex",1);               ====>>>>  #{ sex }
    -->
    <select id="queryUsersByMap" resultType="com.atguigu.pojo.User">
        select
            `id`,`last_name` lastName,`sex`
        from
            t_user
        where
            `last_name` = #{name} or `sex` = #{sex}
    </select>

测试的代码

@Test
public void queryUsersByMap(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        Map<String,Object> map = new HashMap<>();
        map.put("name","ccccccc");
        map.put("sex",1);
        userMapper.queryUsersByMap(map).forEach(System.out::println);
    } finally {
        session.close();
    }
}

一个Pojo数据类型( pojo就是JavaBean )

Mapper接口:

/**
 * 把 User 保存到数据库
 * @param user
 * @return
 */
public int saveUser(User user);

Mapper.xml配置文件:

<!--    /**
    * 把 User 保存到数据库
    * @param user
    * @return
    */
    public int saveUser(User user);
        如果参数是一个javaBean的时候,只需要在#{}占位符中写上对应数据库列的javaBean的属性名即可.
        public class User {
            private Integer id;
            private String lastName;    ====>>>  #{lastName}  表示传递 lastName 属性值给相应的占位符
            private Integer sex;        ====>>>  #{sex}  表示传递 sex 属性值给相应的占位符
    -->
    <insert id="saveUser" parameterType="com.atguigu.pojo.User">
        insert
            into t_user(`last_name`,`sex`)
            values (#{lastName},#{sex})
    </insert>

测试代码:

@Test
public void saveUser(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
       UserMapper userMapper = session.getMapper(UserMapper.class);
       userMapper.saveUser(new User(null,"xxx", 1));
        session.commit();
    } finally {
        session.close();
    }
}

模糊查询

需求:现在要根据用户名查询用户对象。 也就是希望查询如下: select * from t_user where user_name like ‘%张%’

Mapper接口:

/**
 * 根据给定的name值做like模糊查询用户信息
 * @param name
 * @return
 */
public List<User> queryUsersByNameLike(String name);

Mapper.xml配置文件:

<!--    /**
    * 根据给定的name值做like模糊查询用户信息
    * @param name
    * @return
    */
    public List<User> queryUsersByNameLike(String name);-->
    <select id="queryUsersByNameLike" resultType="com.atguigu.pojo.User">
        select
            `id`,`last_name` lastName,`sex`
        from
            t_user
        where
            `last_name` like #{name}
    </select>

测试的代码:

@Test
public void queryUsersByNameLike() {
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);

        String name = "%xx%";

        userMapper.queryUsersByNameLike(name).forEach(System.out::println);

    } finally {
        session.close();
    }
}

${}的使用

在进行order by 排序的时候,不能使用#{},因为会带有双引号,#{}会考虑类型。只能用${},能使用#{}就使用#{}。

#{} 是占位符 , 所以不会有sql注入的问题
${} 是把参数内容原样输出 , 然后和原sql语句做字符串拼接操作. 会有sql注入的安全性问题

#{} 在一个参数的时候,可以任意写内容
${} 里只能写value, 或者使用@Param注解

#{} 一般用于给参数注入值
${} 一般用于表名

MySQL的字符串拼接,concat函数实现。

在这里插入图片描述
在Mapper.xml中的使用:

<!--    /**
    * 根据给定的name值做like模糊查询用户信息
    * @param name
    * @return
    */
    public List<User> queryUsersByNameLike(String name);-->
    <select id="queryUsersByNameLike" resultType="com.atguigu.pojo.User">
        select
            `id`,`last_name` lastName,`sex`
        from
            t_user
        where
            `last_name` like concat('%',#{name},'%');
    </select>

自定义结果集 resultMap标签

resultMap标签可以对查询回来的结果集进行手动映射结果.
就是把查询回来的resultSet表中的数据如何指定哪个列赋值给JavaBean的哪个属性.

resultType 属性它可以指定一个JavaBean的具体类型.让查询回来的resultSet结果集自动映射上列名和属性名相同的属性.

在这里插入图片描述

resultMap的作用。

resultMap标签又叫自定义结果集标签.
resultMap标签经常使用在复杂的Bean对象上.并不会使用在简单的Bean对象上.

简单的Bean对象,是指JavaBean的属性中都是基本的数据类型.
复杂的Bean对象,是指属性的类型又是Bean对象 . 或者是集合的情况.

一般简单的Bean对象 ,都使用resultType属性使用自动映射结果集就可以实现功能效果了.
而复杂的JavaBean才会使用ResultMap标签来进行自定义结果集.

创建一对一数据库表

## 一对一数据表
## 创建锁表
create table t_lock(
	`id` int primary key auto_increment,
	`name` varchar(50)
);


## 创建钥匙表
create table t_key(
	`id` int primary key auto_increment,
	`name` varchar(50),
	`lock_id` int ,
	foreign key(`lock_id`) references t_lock(`id`)
);


## 插入初始化数据
insert into t_lock(`name`) values('阿里巴巴');
insert into t_lock(`name`) values('华为');
insert into t_lock(`name`) values('联想');

insert into t_key(`name`,`lock_id`) values('马云',1);
insert into t_key(`name`,`lock_id`) values('任正非',2);
insert into t_key(`name`,`lock_id`) values('柳传志',3);

创建实体对象

public class Key {
    private Integer id;
    private String name;
    private Lock lock;

public class Lock {
    private Integer id;
    private String name;

一对一级联属性使用

KeyMapper接口:

public interface KeyMapper {
    /**
     * 根据指定key的id值,一次性查询出key所有信息,以及key中lock的信息.
     * @param id
     * @return
     */
    public Key queryKeyById(Integer id);
}

Mapper.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">
<!--
    namespace名称空间的值要改为对应的Mapper接口的全类名
-->
<mapper namespace="com.atguigu.mapper.KeyMapper">

    <!--
        resultMap自定义结果集
            id 唯一标识
            type 每一行转换的具体对象类型
    -->
    <resultMap id="queryKeyByIdResultMap" type="com.atguigu.pojo.Key">
        <!--主键列映射-->
        <id column="id" property="id" />
        <!--非主键列映射-->
        <result column="name" property="name" />
        <!--
            级联属性映射
                级联  ===>>>> 一级一级关联
        -->
        <result column="lock_id" property="lock.id" />
        <result column="lock_name" property="lock.name" />
    </resultMap>
<!--    /**
    * 根据指定key的id值,一次性查询出key所有信息,以及key中lock的信息.
    * @param id
    * @return
    */
    public Key queryKeyById(Integer id);-->
    <select id="queryKeyById" resultMap="queryKeyByIdResultMap">
        select
            t_key.* ,
            t_lock.name lock_name
        from
            t_key left join t_lock
        on
            t_key.lock_id = t_lock.id
        where
            t_key.id = #{id}
    </select>
</mapper>

测试的代码:

public class KeyMapperTest {

    static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init() throws Exception{
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    }

    @Test
    public void queryKeyById() {
        SqlSession session = sqlSessionFactory.openSession();
        try {

            KeyMapper keyMapper = session.getMapper(KeyMapper.class);

            System.out.println(keyMapper.queryKeyById(1));

        } finally {
            session.close();
        }
    }
}

association 标签 嵌套结果集映射配置

association 标签可以给Bean的子对象进行赋值映射操作.

<!--
        resultMap自定义结果集
            id 唯一标识
            type 每一行转换的具体对象类型
    -->
    <resultMap id="queryKeyByIdResultMap" type="com.atguigu.pojo.Key">
        <!--主键列映射-->
        <id column="id" property="id" />
        <!--非主键列映射-->
        <result column="name" property="name" />
        <!--association标签可以配置子对象
               property 属性表示子对象名称
               javaType 表示子对象的全类名
        -->
        <association property="lock" javaType="com.atguigu.pojo.Lock">
            <result column="lock_id" property="id" />
            <result column="lock_name" property="name" />
        </association>
    </resultMap>
<!--    /**
    * 根据指定key的id值,一次性查询出key所有信息,以及key中lock的信息.
    * @param id
    * @return
    */
    public Key queryKeyById(Integer id);-->
    <select id="queryKeyById" resultMap="queryKeyByIdResultMap">
        select
            t_key.* ,
            t_lock.name lock_name
        from
            t_key left join t_lock
        on
            t_key.lock_id = t_lock.id
        where
            t_key.id = #{id}
    </select>

association 定义分步查询

association 标签还可以通过调用一个查询得到子对象.
LockMapper接口:

public interface LockMapper {
    /**
     * 简单查询lock表的信息( 不常用数据 )
     * @param id
     * @return
     */
    public Lock queryLockByLockId(Integer id);
}

LockMapper.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.atguigu.mapper.LockMapper">

<!--    /**
    * 简单查询lock表的信息( 不常用数据 )
    * @param id
    * @return
    */
    public Lock queryLockByLockId(Integer id);-->
    <select id="queryLockByLockId" resultType="com.atguigu.pojo.Lock">
        select `id`,`name` from t_lock where id = #{id}
    </select>
</mapper>

KeyMapper接口:

/**
 * 要两步查询key的信息,一次只查key表的数据<br/>
 * @param keyId
 * @return
 */
public Key queryKeyByKeyIdForTwoStep(Integer keyId);

KeyMapper.xml配置文件:

 <resultMap id="queryKeyByKeyIdForTwoStepResultMap" type="com.atguigu.pojo.Key">
        <id column="id" property="id" />
        <result column="name" property="name"/>
        <!--
            需要调用association标签来调用一个查询从而得到子对象的数据
                property是子对象的属性名
                select 表示调用查询( 由名称空间+id组成 )
                column 属性把指定列的值传递给调用的方法做参数值
        -->
        <association property="lock" column="lock_id"
            select="com.atguigu.mapper.LockMapper.queryLockByLockId"
        />
    </resultMap>
<!--    /**
    * 要两步查询key的信息,一次只查key表的数据<br/>
    * @param keyId
    * @return
    */
    public Key queryKeyByKeyIdForTwoStep(Integer keyId);-->
    <select id="queryKeyByKeyIdForTwoStep"
            resultMap="queryKeyByKeyIdForTwoStepResultMap">
        select `id`,`name`,`lock_id` from t_key where id = #{id}
    </select>

测试的代码:

@Test
public  void queryKeyByKeyIdForTwoStep(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        KeyMapper keyMapper = session.getMapper(KeyMapper.class);

        Key key = keyMapper.queryKeyByKeyIdForTwoStep(1);

        System.out.println(key);
    } finally {
        session.close();
    }
}

延迟加载

延迟加载在一定程序上可以减少很多没有必要的查询。给数据库服务器提升性能上的优化。
要启用延迟加载,需要在mybatis-config.xml配置文件中,添加如下两个全局的settings配置。

	   <!-- 打开延迟加载的开关 -->  
       <setting name="lazyLoadingEnabled" value="true" />  
       <!-- 将积极加载改为消极加载  按需加载 -->  
	   <setting name="aggressiveLazyLoading" value="false"/>  

多对一、一对多的使用示例

  • 创建一对多数据库
## 一对多数据表
## 创建班级表
create table t_clazz(
	`id` int primary key auto_increment,
	`name` varchar(50)
);

## 插入班级信息
insert into t_clazz(`name`) values('javaEE');
insert into t_clazz(`name`) values('C++');
insert into t_clazz(`name`) values('H5');
insert into t_clazz(`name`) values('LUA');

## 创建学生表
create table t_student(
	`id` int primary key auto_increment,
	`name` varchar(50),
	`clazz_id` int,
	foreign key(`clazz_id`) references t_clazz(`id`)
);

## 插入班级信息
insert into t_student(`name`,`clazz_id`) values('javaEE_1',1);
insert into t_student(`name`,`clazz_id`) values('javaEE_2',1);
insert into t_student(`name`,`clazz_id`) values('javaEE_3',1);
insert into t_student(`name`,`clazz_id`) values('C++_1',2);
insert into t_student(`name`,`clazz_id`) values('C++_2',2);
insert into t_student(`name`,`clazz_id`) values('H5_1',3);

collection标签 一对多,立即加载

public class Student {
    private Integer id;
    private String name;

public class Clazz {
    private Integer id;
    private String name;
    private List<Student> stus;

Mapper接口:

public interface ClazzMapper {
    /**
     * 一次性查询出班级和此班级所有学生信息
     * @param clazzId 班级编号
     * @return
     */
    public Clazz queryClazzByClazzIdForSimple(Integer clazzId);
}

mapper.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.atguigu.mapper.ClazzMapper">

    <resultMap id="queryClazzByClazzIdForSimpleResultMap"
               type="com.atguigu.pojo.Clazz">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <!--
            collection标签表示配置集合属性
                property 配置集合的名称
                ofType 配置集合中每个元素的具体类型
        -->
        <collection property="stus" ofType="com.atguigu.pojo.Student">
            <!--
                对于集合,我们需要区分主键列和非主键列
            -->
            <id column="stu_id" property="id" />
            <result column="stu_name" property="name" />
        </collection>
    </resultMap>
<!--    /**
    * 一次性查询出班级和此班级所有学生信息
    * @param clazzId 班级编号
    * @return
    */
    public Clazz queryClazzByClazzIdForSimple(Integer clazzId);-->
    <select id="queryClazzByClazzIdForSimple"
            resultMap="queryClazzByClazzIdForSimpleResultMap">
        select
            t_clazz.*,
            t_student.id stu_id,
            t_student.name stu_name
        from
            t_clazz left join t_student
        on
            t_clazz.id = t_student.clazz_id
        where
            t_clazz.id = #{clazzId}
    </select>
</mapper>

测试的代码:

package com.atguigu.mapper.test;

import com.atguigu.mapper.ClazzMapper;
import com.atguigu.pojo.Clazz;
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.BeforeClass;
import org.junit.Test;

import java.io.IOException;

public class ClazzMapperTest {

    static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init() throws IOException {
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    }

    @Test
    public void queryClazzByClazzIdForSimple() {

        SqlSession session = sqlSessionFactory.openSession();
        try {
            // 获取班级Dao / mapper
            ClazzMapper clazzMapper = session.getMapper(ClazzMapper.class);

            Clazz clazz = clazzMapper.queryClazzByClazzIdForSimple(1);

            System.out.println(clazz);

        } finally {
            session.close();
        }
    }
}

一对多,赖加载

分两次查,最后一次用的时候再查,不用不查.
StudentMapper接口:

public interface StudentMapper {
    /**
     * 根据班级编号查询学生信息
     * @param clazzId
     * @return
     */
    public List<Student> queryStudentsByClazzId(Integer clazzId);
}

StudentMapper.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.atguigu.mapper.StudentMapper">
<!--
    * 根据班级编号查询学生信息
    * @param clazzId
    * @return
    */
    public List<Student> queryStudentsByClazzId(Integer clazzId);-->
    <select id="queryStudentsByClazzId" resultType="com.atguigu.pojo.Student">
        select `id`,`name` from t_student where clazz_id = #{clazzId}
    </select>
</mapper>

ClazzMapper接口

/**
 * 根据班级编号查询班级信息, 分两次查,一次只查班级,一个查班级学生
 * @param clazzId
 * @return
 */
public Clazz queryClazzByClazzIdForTwoStep(Integer clazzId);

ClazzMapper.xml配置文件

 <!--将查询回来的结果封装成为Clazz班级对象-->
    <resultMap id="queryClazzByClazzIdForTwoStepResultMap"
               type="com.atguigu.pojo.Clazz">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <!--
            collection标签可以把查询回来的数据封装成为集合,
            也可以通过调用一个查询得到集合

            property表示集合属性名称
            select 属性表示要调用哪个查询( 名称空间+id值 )
            column表示传递给调用方法的参数( 设置列名 )
        -->
        <collection property="stus" column="id"
            select="com.atguigu.mapper.StudentMapper.queryStudentsByClazzId"
        />
    </resultMap>
<!--    /**
    * 根据班级编号查询班级信息, 分两次查,一次只查班级,一个查班级学生
    * @param clazzId
    * @return
    */
    public Clazz queryClazzByClazzIdForTwoStep(Integer clazzId);-->
    <select id="queryClazzByClazzIdForTwoStep"
            resultMap="queryClazzByClazzIdForTwoStepResultMap">
        select `id`,`name` from t_clazz where id = #{id}
    </select>

多列传值(了解)

多列传值是指在 association标签中或collection标签中调用的查询有多个参数如何传值.
在这里插入图片描述

动态SQL语句

动态的sql语句 ,是指mybatis通过在运行时动态的判断参数的值.从而改变sql的内容.叫动态sql.

准备工作:

public class User {
	private int id;
	private String lastName;
	private int sex;

if 语句

说明: if语句,可以动态的根据你的值来决定,是否需要动态的添加查询条件。

public interface UserMapper {
    /**
     * 根据User对象 name属性 和 sex属性进行查询用户 <br>
     * @param user
     * @return
     */
    public List<User> queryUsersByUser(User user);
}

mapper.xml配置文件:

<select id="queryUsersByUser"
        parameterType="com.atguigu.pojo.User"
        resultType="com.atguigu.pojo.User">
    select
        `id`,`last_name` lastName,`sex`
    from
        t_user
    where
        <!--
            if 判断.如果成立,就执行
         -->
        <if test="lastName != null">
            last_name like concat('%',#{lastName},'%')
        </if>
        <if test="sex == 1 or sex == 0">
            and
            sex = #{sex}
        </if>
</select>

测试代码:

@Test
public void queryUsersByUser() {
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        userMapper.queryUsersByUser(new User(null, "xxx",10)).forEach(System.out::println);
    } finally {
        session.close();
    }
}

where 语句

说明: where语句,可以帮我们在多个动态语句中,有效的去掉前面的多余的and 或 or 之类的多余关键字

mapper.xml配置文件:

<select id="queryUsersByUser"
        parameterType="com.atguigu.pojo.User"
        resultType="com.atguigu.pojo.User">
    select
        `id`,`last_name` lastName,`sex`
    from
        t_user
    <!--
        where标签可以去掉包含的内容前面的and 或 or关键字. 并且如果有内容还会添加where关键字
     -->
    <where>
        <!--
            if 判断.如果成立,就执行
         -->
        <if test="lastName != null">
            last_name like concat('%',#{lastName},'%')
        </if>
        <if test="sex == 1 or sex == 0">
            and
            sex = #{sex}
        </if>
    </where>
</select>

测试的代码:

@Test
public void queryUsersByUser() {
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        userMapper.queryUsersByUser(new User(null, null,10)).forEach(System.out::println);
    } finally {
        session.close();
    }
}

trim语句

说明: trim 可以动态在包含的语句前面和后面添加内容。也可以去掉前面或者后面给定的内容
prefix 前面添加内容
suffix 后面添加内容
suffixOverrides 去掉的后面内容
prefixOverrides 去掉的前面内容

<select id="queryUsersByUser"
        parameterType="com.atguigu.pojo.User"
        resultType="com.atguigu.pojo.User">
    select
        `id`,`last_name` lastName,`sex`
    from
        t_user
    <!--
        trim 标签可以去掉包含内容前面 ,或 后面指定的内容.
        也可以在包含内容的前面 或 后面 添加指定的内容
           prefix 前面添加内容
suffix 后面添加内容
suffixOverrides 去掉的后面内容
prefixOverrides 去掉的前面内容
     -->
    <trim suffixOverrides="and" prefixOverrides="and" prefix="where">
        <!--
            if 判断.如果成立,就执行
         -->
        <if test="lastName != null">
            last_name like concat('%',#{lastName},'%') and
        </if>
        <if test="sex == 1 or sex == 0">
            sex = #{sex}
        </if>
    </trim>
</select>

choose( when , otherwise )语句

说明:choose when otherwise 可以执行多路选择判断,但是只会有一个分支会被执行。

Mapper接口:

public List queryUsersByUserChooseWhenOtherWise(User user);

mapper.xml配置文件:

<select id="queryUsersByUserChooseWhenOtherWise"
            parameterType="com.atguigu.pojo.User"
        resultType="com.atguigu.pojo.User">
    select
        `id`,`last_name` lastName,`sex`
    from
        t_user
    <choose>
        <when test="lastName != null">
            where last_name like concat('%',#{lastName},'%')
        </when>
        <when test="sex == 0 or sex == 1">
            where sex = #{sex}
        </when>
        <otherwise>
            where 1 = 1
        </otherwise>
    </choose>
</select>

测试的代码:

@Test
public void queryUsersByUserChooseWhenOtherWise(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        List<User> users = userMapper.queryUsersByUserChooseWhenOtherWise(new User(null, null, 10));
        users.forEach(System.out::println);
    } finally {
        session.close();
    }
}

set语句

删除条件后的逗号 , 主要应用于 update 语句中

mapper.xml配置文件:

	<!--    public int updateUser(User user);-->
    <update id="updateUser" parameterType="com.atguigu.pojo.User">
        update
            t_user
        <!-- 可以去掉,包含内容后面的逗号,如果有包含的内容.还会添加set关键字 -->
        <set>
            `last_name` = #{lastName} ,
            <if test="sex == 0 or sex == 1">
                `sex` = #{sex}
            </if>
        </set>
        where
            id = #{id}
    </update>

测试的代码:

@Test
public void updateUser(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);

        userMapper.updateUser(new User(16, "updated", 10));

        session.commit();
    } finally {
        session.close();
    }
}

foreach语句

foreach很直观就是遍历
一: 遍历查询条件
select * from 表名 where id in(xx,xx,xx)

Mapper接口:

//    一: 遍历查询条件
//    select * from 表名 where id in(xx,xx,xx)
    public List<User> queryUsersByIds(List<Integer> ids);

Mapper.xml配置文件:

<!--        //    一: 遍历查询条件
        //    select * from 表名 where id in(xx,xx,xx)
        public List<User> queryUsersByIds(List<Integer> ids);-->
    <select id="queryUsersByIds" resultType="com.atguigu.pojo.User">
        select
            `id`,`last_name` lastName,`sex`
        from
            t_user
            <!--
                collection 是遍历的数据源
                item 是遍历到的数据
                separator 遍历的每个元素中的间隔符
                open遍历前输出的内容
                close遍历后输出的内容
             -->
            <foreach collection="list" item="id" separator="," open="where id in (" close=")">
                #{id}
            </foreach>
    </select>

测试的代码:

@Test
public void queryUsersByIds(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(11);
        ids.add(12);
        List<User> users = userMapper.queryUsersByIds(ids);
        users.forEach(System.out::println);
    } finally {
        session.close();
    }
}

二:遍历批量插入
insert into 表名(列,列) values(?,?,?),(?,?,?)
Mapper接口

//    二:遍历批量插入
//    insert into 表名(列,列) values(?,?,?),(?,?,?)
    public int saveUsers(List<User> users);

mapper.xml配置文件:

<!--    //    二:遍历批量插入
    //    insert into 表名(列,列) values(?,?,?),(?,?,?)
    public int[] saveUsers(List<User> users);-->
    <insert id="saveUsers">
        insert into
            t_user(`last_name`,`sex`)
        values
        <foreach collection="list" item="user" separator=",">
            (#{user.lastName},#{user.sex})
        </foreach>
    </insert>

测试的代码:

@Test
public void saveUsers(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        List<User> users = new ArrayList<>();
        users.add(new User(null,"aaa", 1));
        users.add(new User(null,"bbb", 1));
        users.add(new User(null,"ccc", 1));
        userMapper.saveUsers(users);
        session.commit();
    } finally {
        session.close();
    }
}

sql片段

sql片段是我们抽取了多个sql语句中相同的公共部分的内容.用于统一维护的sql叫片段.
在这里插入图片描述

mybatis缓存

缓存: 缓存是指把经常访问的数据保存到高速缓冲区中.
缓存名词又可以理解为,保存中高速缓冲区中的数据.

常见的做法,就是把数据保存起来.方便快速访问.

一级缓存: 同一个sqlSession是一级缓存
二级缓存: 同一个SqlsessionFactory是二级缓存

mybatis的一级缓存的示例

在这里插入图片描述
测试的代码:

@Test
public void testFirstCache() {
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);

        User user = userMapper.queryUserById(1);
        System.out.println(user);

        User user1 = userMapper.queryUserById(1);
        System.out.println(user1);

    } finally {
        session.close();
    }
}
  • 一级缓存的管理
    缓存失效的四种情况:
    1.不在同一个SqlSession对象中
 @Test
    public void queryOne() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = userMapper.queryUserById(1);
            System.out.println(user);
        } finally {
            session.close();
        }
    }
//    缓存失效的四种情况:
//            1.不在同一个SqlSession对象中
    @Test
    public void testFirstCacheFail1(){
        queryOne();
        queryOne();
    }

2.执行语句的参数不同。缓存中也不存在数据。

@Test
public void testFirstCacheFail2(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);

        User user = userMapper.queryUserById(1);
        System.out.println(user);

        User user1 = userMapper.queryUserById(2);
        System.out.println(user1);

    } finally {
        session.close();
    }
}

3.执行增,删,改,语句,会清空掉缓存

  //  3.执行增,删,改,语句,会清空掉缓存
@Test
public void testFirstCacheFail3(){
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);

        User user = userMapper.queryUserById(1);
        System.out.println(user);

        // 只要两次查询中,执行了写操作,,, insert,delete,update操作,缓存就会被清空
        userMapper.insertUser(new User(null,"abc", 1));

        User user1 = userMapper.queryUserById(1);
        System.out.println(user1);

        session.commit();
    } finally {
        session.close();
    }
}

4.手动清空缓存数据

//            4.手动清空缓存数据
    @Test
    public void testFirstCacheFail4(){
        SqlSession session = sqlSessionFactory.openSession();
        try {
            UserMapper userMapper = session.getMapper(UserMapper.class);
            User user = userMapper.queryUserById(1);
            System.out.println(user);
            // clear 清空
            // cache缓存
            session.clearCache();
            User user1 = userMapper.queryUserById(1);
            System.out.println(user1);
            session.commit();
        } finally {
            session.close();
        }
    }

mybatis的二级缓存

二级缓存的图解示意
在这里插入图片描述
二级缓存的使用:
myBatis的二级缓存默认是不开启的。
1 我们需要在mybatis的核心配置文件中配置setting选项
在这里插入图片描述
2 在Mapper.xml的配置文件中加入cache标签。启动二级缓存
在这里插入图片描述
3 被二级缓存的对象必须要实现java的序列化接口。
在这里插入图片描述

二级缓存的演示

public void queryOne() {
    SqlSession session = sqlSessionFactory.openSession();
    try {
        UserMapper userMapper = session.getMapper(UserMapper.class);
        User user = userMapper.queryUserById(1);
        System.out.println(user);
    } finally {
        session.close();
    }
}

@Test
public void testSecondCache(){
    queryOne();
    queryOne();
}

useCache="false"的演示和说明
useCache属性是在select标签中设置查询的结果是否缓存到二级缓存中.默认情况下它的值是true,表示保存到二级缓存中.
在这里插入图片描述
flushCache="false"的演示和说明
当执行insert / update / delete 这些语句的时候,都会清空缓存.
也可以通过在这些标签上使用属性 flushCache=“false” 设置不清空缓存.
在这里插入图片描述

如何自定义二级缓存 ( 知道 )

1 实现Mybatis中提供的Cache接口

public class MyCache implements Cache {
    private final String id;
    private Map<Object, Object> cache = new HashMap();

    public MyCache(String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }

    public int getSize() {
        return this.cache.size();
    }

    /**
     * 保存数据到二级缓存中
     * @param key
     * @param value
     */
    public void putObject(Object key, Object value) {
        System.out.println("保存数据到二级缓存 key : " + key);
        System.out.println("保存数据到二级缓存 value : " + value);
        this.cache.put(key, value);
    }

    /**
     * 从二级缓存中取数据
     * @param key
     * @return
     */
    public Object getObject(Object key) {
        System.out.println("从二级缓存中取数据 key : " + key);
        return this.cache.get(key);
    }

    public Object removeObject(Object key) {
        return this.cache.remove(key);
    }

    public void clear() {
        this.cache.clear();
    }

    public ReadWriteLock getReadWriteLock() {
        return null;
    }

    public boolean equals(Object o) {
        if (this.getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        } else if (this == o) {
            return true;
        } else if (!(o instanceof Cache)) {
            return false;
        } else {
            Cache otherCache = (Cache)o;
            return this.getId().equals(otherCache.getId());
        }
    }

    public int hashCode() {
        if (this.getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        } else {
            return this.getId().hashCode();
        }
    }
}

2 到Mapper.xml中去配置自定义的二级缓存.
在这里插入图片描述

缓存的使用顺序说明:

1、当我们执行一个查询语句的时候。mybatis会先去二级缓存中查询数据。
2 如果二级缓存中没有。就到一级缓存中取数据
3、如果二级缓存和一级缓存都没有。就发sql语句到数据库中去查询。
4、查询出来之后马上把数据保存到一级缓存中。
5、当SqlSession关闭的时候,会把一级缓存中的数据保存到二级缓存中。

mybatis 逆向工程

MyBatis逆向工程,简称MBG。是一个专门为MyBatis框架使用者定制的代码生成器。可以快速的根据表生成对应的映射文件,接口,以及Bean类对象。
逆向工程只能对单表生成CRUD操作

叫 mybatis-generator-core-1.3.2。

它可以帮我们对比数据库表之后,生成大量的这个基础代码。
这些基础代码有:
1、数据库表对应的javaBean对象
2、这些javaBean对象对应的Mapper接口
3、这些Mapper接口对应的配置文件

  	<!-- 去掉全部的注释 -->
	<commentGenerator>
        <property name="suppressAllComments" value="true" />
    </commentGenerator>

准备数据库表

create database mbg;

use mbg;

create table t_user(
	`id` int primary key auto_increment,
	`username` varchar(30) not null unique,
	`password` varchar(40) not null,
	`email` varchar(50)
);

insert into t_user(`username`,`password`,`email`) values('admin','admin','admin@atguigu.com');
insert into t_user(`username`,`password`,`email`) values('wzg168','123456','admin@atguigu.com');
insert into t_user(`username`,`password`,`email`) values('admin168','123456','admin@atguigu.com');
insert into t_user(`username`,`password`,`email`) values('lisi','123456','admin@atguigu.com');
insert into t_user(`username`,`password`,`email`) values('wangwu','123456','admin@atguigu.com');

create table t_book(
	`id` int primary key auto_increment,
	`name` varchar(50),
	`author` varchar(50),
	`price`	decimal(11,2),
	`sales`	int,
	`stock` int
);


## 插入初始化测试数据
insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , 'java从入门到放弃' , '国哥' , 80 , 9999 , 9);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , '数据结构与算法' , '严敏君' , 78.5 , 6 , 13);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , '怎样拐跑别人的媳妇' , '龙伍' , 68, 99999 , 52);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , '木虚肉盖饭' , '小胖' , 16, 1000 , 50);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , 'C++编程思想' , '刚哥' , 45.5 , 14 , 95);

insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , '蛋炒饭' , '周星星' , 9.9, 12 , 53);
 
insert into t_book(`id` , `name` , `author` , `price` , `sales` , `stock` ) 
values(null , '赌神' , '龙伍' , 66.5, 125 , 535);

select * from t_user;
select * from t_book;

逆向工程配置文件

<?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>

    <!--
        targetRuntime 可以设置生成的版本
            MyBatis3         豪华版  除了CRUD还有很多有用的查询方法
            MyBatis3Simple   标配版   只有CRUD
    -->
    <context id="DB2Tables" targetRuntime="MyBatis3">

        <!-- 去掉全部的注释 -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>

        <!--
            修改 数据库的 连接属性
        -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mbg"
                        userId="root"
                        password="root">
        </jdbcConnection>

        <javaTypeResolver >
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--配置生成javaBean的
                targetPackage javaBean的包名
                targetProject 生成在哪个项目目录下
        -->
        <javaModelGenerator targetPackage="com.atguigu.pojo" targetProject=".\08-mybatis-mbg\src">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--
                   配置生成的Mapper.xml配置文件
                                   targetPackage javaBean的包名
                                targetProject 生成在哪个项目目录下
        -->
        <sqlMapGenerator targetPackage="com.atguigu.mapper"  targetProject=".\08-mybatis-mbg\src">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        <!--
            配置生成Mapper接口
                targetPackage Mapper接口的包名
                targetProject 生成在哪个项目目录下
        -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mapper"
                             targetProject=".\08-mybatis-mbg\src">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <!--
            数据库一个表对应一个table标签
                tableName是表名
                domainObjectName 设置生成的类名
        -->
        <table tableName="t_user" domainObjectName="User" />
        <table tableName="t_book" domainObjectName="Book" />
    </context>
</generatorConfiguration>

执行逆向工程的代码:

package com.atguigu.mbg.runner;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MbgRunner {

    public static void main(String[] args) throws IOException, XMLParserException, InvalidConfigurationException, SQLException, InterruptedException {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("08-mybatis-mbg/mbg.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }
}

在这里插入图片描述
土豪金版本的测试代码:

package com.atguigu.test;

import com.atguigu.mapper.BookMapper;
import com.atguigu.pojo.Book;
import com.atguigu.pojo.BookExample;
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.BeforeClass;
import org.junit.Test;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;

public class BookMapperTest {

    static SqlSessionFactory sqlSessionFactory;

    @BeforeClass
    public static void init() throws IOException {
        sqlSessionFactory= new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
    }

    @Test
    public void countByExample() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            BookMapper mapper = session.getMapper(BookMapper.class);
            // 创建一个条件类
            BookExample bookExample = new BookExample();
            // 创建一个查询条件
            BookExample.Criteria criteria = bookExample.createCriteria();

//            where xxx = xxx and xxx = xxx;
//            where xxx = xxx or xxx = xxx;

            // 查询价格大于16的图书有几条记录
//            criteria.andPriceGreaterThan(new BigDecimal(16));
            // 查询销量大于10 , 且 库存 大于50的记录
//            criteria.andSalesGreaterThan(10);
//            criteria.andStockGreaterThan(50);

            // 查询销量大于10 , 或 库存 大于50的记录
            criteria.andSalesEqualTo(10);
            bookExample.or().andStockGreaterThan(50);

            // count() 用于查询数量的方法
            // count 用于查询数量的
            // ByExample按条件来查询
            int i = mapper.countByExample(bookExample);

            System.out.println(i);
        } finally {
            session.close();
        }

    }

    @Test
    public void deleteByExample() {
        SqlSession session = sqlSessionFactory.openSession();
        try {
            BookMapper mapper = session.getMapper(BookMapper.class);
//            mapper.deleteByExample(null);// 只要条件是空,就是全表操作
            BookExample bookExample = new BookExample();
            bookExample.createCriteria().andSalesGreaterThan(10000);

            mapper.deleteByExample(bookExample);

            session.commit();
        } finally {
            session.close();
        }

    }

    @Test
    public void deleteByPrimaryKey() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            mapper.deleteByPrimaryKey(8);

            session.commit();
        } finally {
            session.close();
        }

    }

    @Test
    public void insert() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            mapper.insert(new Book(null,"拐跑别人媳妇", "陈凯", new BigDecimal(1234), 1234,1234));
            mapper.insert(new Book(null,"伟德渣男记", "王灿侨", new BigDecimal(1234), 1234,1234));

            session.commit();

        } finally {
            session.close();
        }

    }

    @Test
    public void insertSelective() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            Book book = new Book(null,"国哥是怎样炼成的", null,null,100,100);

            // 方法末尾Selective就表示操作的时候,不带null值的列
//            mapper.insertSelective(book);// null列不在操作范围内
            mapper.insert(book);// null列一样在操作范围内

            session.commit();
        } finally {
            session.close();
        }

    }

    @Test
    public void selectByExample() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            BookExample bookExample = new BookExample();
            bookExample.createCriteria().andIdBetween(1,10);
            // 设置排序字段
            bookExample.setOrderByClause(" price desc ");
//            List<Book> books = mapper.selectByExample(null);// 条件为null,就整表操作
            List<Book> books = mapper.selectByExample(bookExample);// 有条件

            books.forEach(System.out::println);

        } finally {
            session.close();
        }

    }

    @Test
    public void selectByPrimaryKey() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            Book book = mapper.selectByPrimaryKey(6);

            System.out.println(book);

        } finally {
            session.close();
        }

    }

    @Test
    public void updateByExampleSelective() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            Book book = new Book(null,"忽略null的列", null, null,1234,124);
            BookExample bookExample = new BookExample();
            bookExample.createCriteria().andIdGreaterThan(8);
            /**
             * 根据条件来进行更新,而且不带null的列
             */
            mapper.updateByExampleSelective(book,bookExample);

            session.commit();

        } finally {
            session.close();
        }

    }

    @Test
    public void updateByExample() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            Book book = new Book(null,"忽略null的列", null, null,1234,124);
            BookExample bookExample = new BookExample();
            bookExample.createCriteria().andIdGreaterThan(8);
            /**
             * 根据条件来进行更新,而且不带null的列
             */
            mapper.updateByExample(book,bookExample);

            session.commit();

        } finally {
            session.close();
        }
    }

    @Test
    public void updateByPrimaryKeySelective() {
        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            Book book = new Book(null,"忽略null的列", null, null,1234,124);

            /**
             * 根据条件来进行更新,而且不带null的列
             */
            mapper.updateByPrimaryKeySelective(book);

            session.commit();

        } finally {
            session.close();
        }
    }

    @Test
    public void updateByPrimaryKey() {

        SqlSession session = sqlSessionFactory.openSession();

        try {
            BookMapper mapper = session.getMapper(BookMapper.class);

            Book book = new Book(null,"忽略null的列", null, null,1234,124);

            /**
             * 根据条件来进行更新
             */
            mapper.updateByPrimaryKey(book);

            session.commit();

        } finally {
            session.close();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

destiny- freedom

感觉怎么样呐?

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

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

打赏作者

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

抵扣说明:

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

余额充值