MyBatis 是一款优秀的持久层框架,用于简化 JDBC 开发。
1.持久层:
负责将数据到保存到数据库的那一层代码
JavaEE三层架构:表现层、业务层、持久层
2.框架:
①框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型;
②在框架的基础之上构建软件编写更加高效、规范、通用、可扩展。

MyBatis配置环境

Mybatis配置环境-天龙八步.png
第一步:新建模块,image.png
第二步:导jar包,image.png,点进pom.xml文件中,jar包文件
注意在image.png的下面jar包(因为xml文件有约束),pom依赖坐标.xml,把文件复制粘贴到image.png里面,点击刷新image.png
jar包生成在了这里image.png
第三步:复制logback.xmlimage.png中。

第四步:在java下创建mapper和pojo包image.png,根据数据库中的字段名在pojo包下 编写类(成员属性:日期是这个类型————image.png)。
第五步:将文件mybatis-config.xml复制到image.png,并且修改参数 image.png,固定修改image.png 注意图中day18为MySQL中的数据库名,写image.png接口映射文件位 置,为“XXXMapper.xml”—XXX给类名。
第六步:在mapper包下编写接口。

第七步:将xxxMapper.xmlXXXMapper.xml文件复制到 image.png中,XXX改 为”类名Mapper.xml”,修改XXXMapper.xml文件中的 image.png的参数,包名.接口 名为:image.png,写方法名,方法返回值类型为: image.png,编写SQL语句,
修改之后变成:image.png
第八步:编写测试类,在pojo包下创建,
前三行为固定:1.String resource = “mybatis-config.xml”;
2.InputStream inputStream = Resources.getResourceAsStream(resource);
3.SqlSessionFactory sqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);
黑马.png

MyBatis 核心配置文件(对配置环境进行优化)

typeAliases标签:给包.类起别名,让类使用更简单。
mapper标签:加载接口映射文件。

在mybatis-config.xml文件中:

  1. <typeAliases>
  2. <!--typeAlias:给实体类取别名 type:包名.类名 alias:别名,一般别名就是类名,别名在使用时不区分大小写-->
  3. <!--<typeAlias type="com.itheima.pojo.User" alias="User"/>
  4. <typeAlias type="com.itheima.pojo.Employee" alias="Employee"/>
  5. <typeAlias type="com.itheima.pojo.Dog" alias="Dog"/>-->
  6. <!--每个实体类都配置一个别名,太麻烦了,
  7. 有简单的方案package:包扫描,扫描一个包中所有实体类,并且别名就是类名name:包名-->
  8. <package name="com.itheima.pojo"/>
  9. </typeAliases>

注意:typeAliases要放在配置environments的前面(XML文件有约束)

<mappers>
        <!--告诉MyBatis接口中对应的SQL语句在这个文件中-->
        <!--<mapper resource="UserMapper.xml"/>
        <mapper resource="DogMapper.xml"/>
        <mapper resource="EmployeeMapper.xml"/>-->
        <!--mapper:只能指定一个映射文件的位置,不方便,有更好的方案-->
        <!--package:包扫描,扫描这个包中所有的接口和映射文件name:包名,写接口所在的包名
        需要两个前提:
                  1.接口名和接口的映射文件名要一样
                  2.接口名接口名和接口的映射文件编译后要在同一个包中-->

        <mapper resource="com.itheima.mapper"/>
    </mappers>

注意:mappers要放在配置environments的后面(XML文件有约束)

MyBatis增删改查

基本增删改查

①在接口中添加方法:
image.png
②在接口映射文件UserMapper.xml配置SQL语句:
image.png
image.png
③执行方法:

@Test
public void test01() throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession sqlSession = sqlSessionFactory.openSession(true);//自动提交事务
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//通过id查询用户
User user = mapper.selectById(1);
System.out.println(user);
//sqlSession.commit();手动添加事务
sqlSession.close();//关闭资源
    }

<!-- update:配置修改的SQL语句
参数是自定义对象:#{成员变量名},先使用?占位,取出参数成员变量值给?赋值
username=#{username}:  username是表中的字段名,#{username}先使用?占位,取出参数成员变量给?赋值-->
<update id="update">
  UPDATE user
  <set>
    <if test="username!=null and username!=''">
      username=#{username},
    </if>
    <if test="birthday!=null">//只有字符串才需要判断是否为空
      birthday=#{birthday},
    </if>
    <if test="sex!=null and sex!=''">
      sex=#{sex},
    </if>
    <if test="address!=null and address!=''">
      address=#{address}
    </if>
  </set>
  WHERE id=#{id};
    </update>

 <!-- delete:配置删除的SQL语句
         注意增删改不需要配置reslutType:增删改的返回值都是影响的行数-->
    <delete id="deleteBuId">
    DELETE FROM user WHERE id=#{uid}
    </delete>

    <!--insert:配置插入的SQL语句
        参数是自定义对象:#{成员变量名}
        useGeneratedKeys:要得到自增的主键
        keyProperty="id":类中的id成员变量保存自增的主键
        -->
    <insert id="add" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user VALUES (NULL,#{username},#{birthday},#{sex},#{address});
    </insert>

useGeneratedKeys:要得到自增的主键
keyProperty=”id”:类中的id成员变量保存自增的主键
映射配置文件小结:
image.png

当多参数查询时

                                                                      (起别名)<br />**参数接收三种方法:**①散装参数: 如果方法中有多个参数,需要使用@Param("SQL参数占位符名称")<br />    ②对象参数: 对象的属性名称要和参数占位符名称一致<br />        ③Map集合参数: Map的键要和占位符名称一致<br />在写接口时:
//批量删除
    void deleteByIds(@Param("ids")int[] ids);//int [] ids={1,4}
    //根据用户名和性别查询用户(多参数处理)
    //方案1:给多个参数设置@Param("名字")注解,在SQL语句中#{名字}
        //List<User> selectByCondition(@Param("username")String username,@Param("sex") String sex);
    //方案2:使用自定义对象保存多个数据
        //List<User> selectByCondition(User user);
    //方案3:使用Map集合保存多个数据,在SQL语句中#{键}取出值
    List<User> selectByCondition(Map<String,String> map);

在测试类中:

@Test
    public void test05() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession sqlSession = sqlSessionFactory.openSession(true);//自动提交事务
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        //方案1
        //List<User> users = mapper.selectByCondition("%精%", "女");

        //方案2
        /*
        User u = new User();
        u.setUsername("%精%");
        u.setSex("女");
        List<User> users = mapper.selectByCondition(u);
        */

        //方案3
        HashMap<String, String> map = new HashMap<>();
        map.put("username","");
        map.put("sex","妖");//null:对象为null(你没有女朋友)    "":空字符串,没有内容的字符串(你有女朋友,但没有灵魂)
        List<User> users = mapper.selectByCondition(map);
        users.forEach(System.out::println);
        //sqlSession.commit();手动添加事务
        sqlSession.close();

动态SQL

1.if: 如果条件为true, 拼接里面的SQL。
2.where: 相当于WHERE关键字, 会去掉多余的 AND OR。
3.set: 用在update语句中,相当于set关键字;去掉SQL代码片段中后面多余的逗号。
4.foreach: 遍历数组或集合, 相当于Java中的增强for。
(在上面下面代码中有体现)

<!--根据用户名和性别查询用户(多参数处理)
    if标签的test属性里面直接写名字,不需要写#{名字}-->
    <select id="selectByCondition" resultType="com.itheima.pojo.User">
        SELECT * FROM user
            <where>
                <if test="username!=null and username!=''">//这里的and不能是AND大写
                    username LIKE #{username}
                </if>
                <if test="sex!=null and sex!=''">
                AND sex=#{sex};
                </if>
            </where>
    </select>

    <delete id="deleteByIds">
        DELETE FROM USER WHERE id IN
    <!-- 我们要遍历的内容:(1,4);
    foreach:遍历数组或集合
        collection:要遍历的数组或集合,在UserMapper.java中@Param(别名)起别名
        item:要遍历出的元素,名字自定义
        open:遍历前添加的内容
        separator:分隔符,在元素之间添加的内容
        close:遍历结束添加的内容
    -->
        <foreach collection="ids" item="id" open="(" separator="," close=");">
            #{id}
        </foreach>
    </delete>

sql和include标签(了解)

image.png

resultMap输出映射(查询结果的字段名称和类的成员变量名不一致时)

image.png
两种方法解决:
①在核心配置文件中使用settings设置mapUnderscoreToCamelCase为true将映射下划线为驼峰 命名法。(核心配置文件在MyBatis官网中找复制粘贴到映射配置文件”XXXMapper.xml”中,注意要把false改成true!)
②使用resultMap解决:resultMap可以建立查询的列与对象属性的对应关系。
jj.png

MyBatis多表查询

MyBatis的工具类,简化MyBatis代码:

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 java.io.IOException;
import java.io.InputStream;
// 这是MyBatis的工具类,简化MyBatis代码
public class MyBatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    // 我们只需要一个SqlSessionFactory,在静态代码块中创建SqlSessionFactory
    static {
        try {
            // 编写代码让MyBatis跑起来,执行SQL语句
            String resource = "mybatis-config.xml";
            // 加载核心配置文件
            InputStream inputStream = Resources.getResourceAsStream(resource);
            // 得到SqlSession工厂,赋值给成员变量
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 返回SqlSessionFactory
    public static SqlSessionFactory getSqlSessionFactory() {
        return sqlSessionFactory;
    }
    // 返回SqlSession,不带事务的
    public static SqlSession openSession() {
        return sqlSessionFactory.openSession();
    }
     //开启自动提交事务
    public static SqlSession openSession(boolean autoCommit) {
        return sqlSessionFactory.openSession(autoCommit);
    }
}

一对一关联

第一步:创建实体类,在实体类中
image.png
当添加了image.png时,记得重新生成getset方法。(注意区分数据类型UserInfo和变量名userInfo)

第二步:编写接口image.png,返回值为User,包含 了User和UserInfo的数据。

第三步:在XXXMapper.xml中编写SQL语句
image.png
image.png
image.png
注:
1.resultType: 自动映射,表中的字段和类中的成员变量一样的才有数据
2.resultMap: 结果映射,处理表中字段和类中成员变量不一样的.手动指定对应关系.多表查询必须要用 resultMap
3.多表查询表中字段名和类中成员变量一样的也要指定, 如果指定autoMapping=”true”就可以不用写,主键一定要写
4.id: 名字,随便取,后面要使用
5.type: 数据保存到这个类的对象中

第四步:编写测试类
image.png

一对多查询

第一步:创建实体类
image.png
第二步:编写接口
image.png
第三步:在XXXMapper.xml中编写SQL语句
image.png
image.png
image.png
第四步:编写测试类

多对多查询

两个一对多
下面例题为三表查询:
1.image.png
2.image.png
3.
image.png
4.image.png
5.image.png
注意:两个一对多之间的实体类都重写了toString方法,可能会出现一直互相打印的情况(递归),所以要删除一个实体类的toString方法。

在一对多或多对多的ofType和javaType使用情境

你去看看无论是collection标签还是association标签里面都需要写property这个标签吧?找到collection标签还是association标签所在的xml文件对应的实体类中property标签的值是什么类型的?如果是集合如图一,就用ofType,并且ofType的值是集合中存储元素的类型。如果不是集合如图二,就用javaType,并且javaType的值是实体类中属性的类型。

ofType:

①根据property标签所在xml文件,对应到实体类User文件,找到property标签的值。
②发现property标签的值accounts在User文件中的类型是泛型为Account的List集合。
③因为是集合,所以选择使用ofType标签(写成集合是因为两个表之间是一对多或者多对多关系,我这里是一个用户可以拥有多个账户,一对多关系)。
④集合中存储的元素类型是Account类型,所以ofType的值是account。
image.png

JavaType:

image.png

MyBatis注解开发

image.png
注解开发只适用于简单的增删改查。

MyBatis缓存

MyBatis高级.pptx

MyBatis批量插入

@Test
    public void test08() {
        // 记录开始时间
        long start = System.currentTimeMillis();                                // MyBatis批量插入
        SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        for (int i = 0; i < 10000; i++) {
            User user = new User(0, "黑熊精"+i, Date.valueOf("1999-09-09"), "妖", "普陀山");
            mapper.add(user);
        }

        sqlSession.commit();//提交事务
        sqlSession.close();

        // 记录结束时间
        long end = System.currentTimeMillis();
        // 消耗时间 = 结束时间 - 开始时间
        System.out.println("消耗时间: " + (end - start));
    }
}

SqlSession sqlSession = MyBatisUtils.getSqlSessionFactory().openSession(ExecutorType.BATCH);
// MyBatis批量插入
批量插入只提交了一个事务,多个事务时是影响性能的。