MyBatis

目录

一、MyBatis概述

        1、1 框架

        1、2 MyBatis与JDBC

        1、3 三层架构

二、MyBatis第一个入门程序

三、使用MyBatis完成CRUD操作

(1)向数据表进行insert操作

(2)向数据表进行update操作

(3)向数据表进行delete操作

(4)向数据库进行select操作

四、MyBatis核心配置文件

(1)properties

(2)transactionManager

(3)datasource

(4)properties

(5)mapper

五、在WEB中应用MyBatis(使用MVC架构模式)

(1)创建一个新的module

 (2)在webapp创建index.html文件

(3)创建mybatis核心配置文件和SQL映射文件

(4)搭建控制层和持久层

(5)搭建tomcat

六、MyBatis中使用接口代理getMapper 

(1)将mapper实现类删掉

(2)更新Service实现类

(3)更新SQL映射文件

七、MyBatis小技巧

(1)#{}和${}

(2)typeAliases

(3)mapper

八、MyBatis参数处理

(1)通过map集合传参

(2)实体类传参

(3)@Param注解传参

九、MyBatis查询语句专题

(1)as起别名

(2)使用resultMap结果映射

(3)开启驼峰式命名

十、MyBatis高级映射及延迟加载

(1)级联属性(了解)

(2)association

(3)分布查询 

十一、MyBatis的缓存机制

(1)一级缓存

(2)二级缓存

十二、MyBatis逆向工程

(1)第一步

(2) 第二步

十三、MyBatis分页查询

(1)limi分页

(2)PageHelper插件 

十四、MyBatis注解开发

(1)@insert

(2)@delete

(3)@Update


一、MyBatis概述


        1、1 框架

                java常用的框架有SSM、SpringBoot、SpringCloud等。

                其中,MyBatis属于SSM框架之一,MyBatis是对JDBC进行封装后的简化框架

                学习MyBatis之前,需要先学习JDBC。

                对SSM三大框架建议学习顺序:

                        MyBatis、Spring、SpringMVC

                        Spring、Mybatis、SpringMVC

        1、2 MyBatis与JDBC

         MyBatis是对JDBC进行封装后的简化框架,底层还是会执行JDBC代码,只是程序员使用MyBatis对数据库进行CRUD(CRUD:增删改查)等操作,不需要像JDBC一样写太繁琐的代码,提高了开发效率。

        JDBC代码:

//sql语句写死在java程序中
String sql = "insert into t_user(id,user_name,user_pwd) values(?,?,?)"

PreparedStatement ps = con.prepareStatement(sql);
//以下代码太过繁琐
ps.setString(1,"1");
ps.setString(2,"张三");
ps.setString(3,"123");

//这里只是传3个值,如果是10多个呢,是不是要多写几个ps.setString方法


int count = ps.executeUpdate();

MyBatis有XML开发、注解开发。在官方解释中,对于复杂的SQL语句,如果使用注解开发,会让你的SQL语句更加混乱,因此,如果是简单的CRUD操作可以使用注解开发,如果是要做一些复杂的操作,最好使用XML来映射。

        1、3 三层架构

         学习MyBatis之前,应该知道什么是MVC三层架构。MyBatis是属于三层架构中的数据持久层。

        MVC三层架构图:

                作者建议: 学习完Spring、SpringMVC之后,可以尝试自己做一个基于SSM的Web项目。因为后期SSM整合之后,堪称“地狱配置”,很多小伙伴学习到SpringMVC,会把前面Spring、MyBatis遗忘,使用SSM做一个项目,可以巩固一下知识,后期学习SpringBoot就不需要担心那么多配置。

二、MyBatis第一个入门程序

        学习MyBatis之前,最好先去学习一下Maven(你就不用手动下载依赖了)

        话不多说,直接上号!!!

      

先准备好一张数据库表t_user,这里的id是主键自增

      1、创建一个Maven项目,这里使用JDK17(或者JDK8)

                 

        2、 创建完Maven项目后,在pom.xml文件中添加依赖(不要看见这么多字就被劝退,这只是一些jar包,帮助你开发的),添加完依赖后记得给Maven刷新一下 ps:如果第一次引入依赖,会出现红字,刷新一下Maven就可以了

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.30</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
</dependencies>

 在resourece目录下创建一个xml文件,命名为mybatis-config.xml(命名无所谓)

 

 在mybatis-config.xml核心配置文件中,写入数据库账号密码(可以直接复制,只修改自己的数据库账号和密码)

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

    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="t_user.xml"/>
    </mappers>
</configuration>

        3、在resources创建SQL映射XML文件,命名t_user.xml

        

        在映射文件中,写入sql语句(这里的namespace先随便写)

        sql映射文件记得写到核心配置文件中!!(<mappers>标签中)

<?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="abc">
    <select id="select" resultType="pojo.User">
        select id,user_name userName,user_pwd userPwd from t_user where id=#{id}
    </select>
</mapper>

 编写java程序

1、创建pojo类

package pojo;

public class User {
    private Integer id;
    private String userName;
    private String userPwd;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", userPwd='" + userPwd + '\'' +
                '}';
    }

    public Integer getId() {
        return id;
    }

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

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPwd() {
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }

    public User(Integer id, String userName, String userPwd) {
        this.id = id;
        this.userName = userName;
        this.userPwd = userPwd;
    }

    public User() {
    }
}

2、查询数据

public class mybatis {
    @Test
    public void test1(){
        try {
            //SqlSessionFactoryBuilder的作用就是创建SqlSessionFactory
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

            //SqlSessionFactory对应一个数据库
            SqlSessionFactory sqlSessionFactory = builder.build(is);
            SqlSession sqlSession = sqlSessionFactory.openSession();

            //pojo类已经实现toString,可以不用转成User类
            //这里是"select"要跟sql映射文件中的<select>标签的id保持一致
            Object user = sqlSession.selectOne("select", 1);
            
            //将映射结果输出
            System.out.println(user);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3、查询结果

三、使用MyBatis完成CRUD操作

        第一个入门程序很简单吧,接下来把CRUD操作也做一遍吧。

        加油,未来的java高级开发工程师.

(1)向数据表进行insert操作

 在sql映射文件中编写sql语句

        (注意这里id是null,因为是主键自增,它会自动给id赋值)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="abc">
    
    <insert id="insert">
        insert into t_user(id,user_name,user_pwd) values(null,"赵六","10086")
    </insert>

</mapper>

编写java程序

public class mybatis {
    @Test
    public void insert(){
        try {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //这里是"insert"要跟sql映射文件中的<insert>标签的id保持一致
            int count = sqlSession.insert("insert");
            sqlSession.commit();//手动提交事物
            System.out.println("插入"+count+"条数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

执行结果

(2)向数据表进行update操作

在sql映射文件中编写sql语句

<?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="abc">

    <update id="update">
        update t_user set user_name="java高级开发工程师",user_pwd="root" where user_name="张三"
    </update>

</mapper>

编写Java程序

public class mybatis {

    @Test
    public void update(){
        SqlSessionFactory sqlSessionFactory = null;
        try {
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //这里是"update"要跟sql映射文件中的<update>标签的id保持一致
            int count = sqlSession.update("update");
            sqlSession.commit();//手动提交事物
            System.out.println("更新了"+count+"条数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

执行结果

(3)向数据表进行delete操作

在sql映射文件中编写sql语句

<?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="abc">

    <delete id="delete">
        delete from t_user where user_name="李四"
    </delete>

</mapper>

编写java程序

public class mybatis {

    @Test
    public void delete(){
        try {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //这里是"delete"要跟sql映射文件中的<delete>标签的id保持一致
            int count = sqlSession.delete("delete");
            sqlSession.commit();//手动提交事物
            System.out.println("删除"+count+"条数据");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

执行结果

        “李四”的数据被删除了

(4)向数据库进行select操作

这里不再演示只查一条记录,只查一条记录在入门程序已经展示过了。

查所有记录,<select>标签需要给resultType属性赋值,告诉mybatis你要映射的实体类是什么(带包名),也可以用map集合映射等等。

在sql映射文件中编写sql语句

<?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="abc">

    <select id="selectAll" resultType="pojo.User">
        select id,user_name userName,user_pwd userPwd from t_user
    </select>

</mapper>

编写java程序

public class mybatis {

    @Test
    public void selectAll(){
        try {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //这里是"selectAll"要跟sql映射文件中的<selectAll>标签的id保持一致
            List<User> users = sqlSession.selectList("selectAll");
            //以下是jdk8的新特性,将集合内容输出
            users.forEach(user -> System.out.println(user));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

执行结果

四、MyBatis核心配置文件

(1)properties

        <properties/>标签有两个属性:resource、url,其中最常用的是resource属性

        resource标签

        (1)在类的根目录下创建一个properties文件

        

         (2)将以下内容复制到properties文件中

        

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=123456

         (3)在mybatis核心配置文件中配置properties标签的resource属性

<properties resource="jdbc.properties"/>

         (4)在mybatis核心配置文件中配置environment标签

<environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

         (5)运行程序

分析: 如果数据库登录信息被修改,不需要修改代码,只需要将properties文件中的配置信息更新即可,假如你写好一个项目交给客户,客户又不懂代码,那你只需要告诉他将数据库的账号密码写入properties文件中,不过一般不这么做,因为客户可能在更新账号密码的时候将jdbc.xxx=删除,但是他又不懂代码,这时就出现报错了。这里只是告诉你properties的用法。

        url标签(不建议使用)

url的用法跟resource的用法差不多,只是url用的是绝对路径,你可以把properties文件放到你想放的地方,但不建议这么做,因为这样会降低程序的移植性,如果存放到类的根目录下,那你整个项目移动到别的设备,路径也不会报错。

使用url只需要修改以下地方,将properties文件放到你想放的位置,我这里放到电脑D盘的位置

<properties url="file:///d:/jdbc.properties"/>

        执行程序

         注意这里的file:后面加的是三条反斜杠,再加路径

(2)transactionManager

        transactionManager标签有一个type属性,该属性有两个值:JDBCMANAGED

        当type属性为JDBC

<environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
</environments>

MyBatis会采用原生的JDBC事物管理,底层还是会调用JDBC的事物。

开启事物:con.setAutoCommit(false);

提交事物:con.commit();

        当type属性为MANAGED

<environments default="dev">
        <environment id="dev">
            <transactionManager type="MANAGED"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
</environments>

MyBatis会放弃原生的JDBC事物管理,把事物交给其他容器去管理,如spring。

如果没有其他容器,则每执行一条DML语句,就提交一次事物。

(3)datasource

        datasource标签的type属性的值有:UNPOOLEDPOOLEDJNDI

        UNPOOLED:不会使用连接池,即每次都会创建一个新的jdbc对象

        POOLED:使用连接池,这个连接池是mybatis实现的数据库连接池

        POOLED的其他属性:

        poolMaximumActiveConnections:最⼤的活动的连接数量。默认值10

        poolMaximumIdleConnections:最⼤的空闲连接数量。默认值5

        poolMaximumCheckoutTime:强⾏回归池的时间。默认值20秒。

        poolTimeToWait:当⽆法获取到空闲连接时,每隔20秒打印⼀次⽇志

        JNDI:表示对接JNDI服务器中的连接池,简单说就是第三方连接池。如dbcp、c3p0、druid(德鲁伊)等,就需要采用这种方式。

(4)properties

        properties不仅可以引入外部文件,还可以这样写,同样也是用¥{}引用。

<properties resource="jdbc.properties">
        <property name="jdbc.username" value="root"/>
        <property name="jdbc.password" value="123456"/>
</properties>

(5)mapper

        mapper标签是用来指定SQL映射文件的路径。

        SQL映射⽂件的配置⽅式包括四种:
        resource:从类路径中加载
        url:从指定的全限定资源路径中加载
        class:使⽤映射器接⼝实现类的完全限定类名
        package:将包内的映射器接⼝实现全部注册为映射器

        resource

        这种方式加载SQL映射文件,需要将文件放到resources目录下或者子目录

<mappers>
        <mapper resource="t_user.xml"/>
</mappers>

        url

        同样也是用绝对路径,将SQL映射文件放到你想放的地方,再用绝对路径进行引用,当然这种方法也不建议,这样会导致程序的移植性差。

<mappers>
        <mapper url="file:///D:/t_user.xml"/>
</mappers>

class和package在文章第七点下面讲解。

五、在WEB中应用MyBatis(使用MVC架构模式)

(1)创建一个新的module

 

 (2)在webapp创建index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我的第一个web项目-mybatis</title>
</head>
<script type="text/javascript">
    window.onload=function () {
        document.getElementById("btn").onclick=function () {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState==4) {
                    if (xhr.status>=200&&xhr.status<300) {
                        document.getElementById("myspan").innerHTML=xhr.responseText
                    }
                }
            }
            var username = document.getElementById("username").value;
            xhr.open("GET","/web/first?username="+username,true)
            xhr.send()
        }
    }
</script>

<body>
    <h2>查询密码</h2>
    请输入要查询的用户:<input type="text" id="username"><br>
    <input type="button" id="btn" value="提交">
    密码:<span id="myspan"></span>
</body>
</html>

(3)创建mybatis核心配置文件和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 default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="User.xml"/>
    </mappers>
</configuration>

SQL映射文件

<?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="user">
    <select id="selectUserPwd" resultType="com.pojo.User">
        select user_name username,user_pwd password from t_user where user_name=#{username}
    </select>
</mapper>

(4)搭建控制层和持久层

 controller类

package com.controller;

import com.service.UserService;
import com.service.impl.UserServiceImpl;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/first")
public class controller extends HttpServlet {

    UserService userService = new UserServiceImpl();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        //获取用户名字
        String username = request.getParameter("username");
        String pwd = userService.selectUserPwd(username);
        out.print(pwd);
    }
}

 service接口以及实现类

package com.service;

public interface UserService {
    //查询用户密码
    String selectUserPwd(String username);
}
package com.service.impl;

import com.mapper.UserMapper;
import com.mapper.impl.UserMapperImpl;
import com.service.UserService;

public class UserServiceImpl implements UserService {

    UserMapper userMapper = new UserMapperImpl();

    @Override
    public String selectUserPwd(String username) {
        return userMapper.selectPwd(username);
    }
}

mapper接口以及实现类

package com.mapper;

public interface UserMapper {
    //查询密码
    String selectPwd(String username);
}
package com.mapper.impl;

import com.mapper.UserMapper;
import com.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 java.io.IOException;

public class UserMapperImpl implements UserMapper {
    @Override
    public String selectPwd(String username) {
        User user = null;
        try {
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"));
            SqlSession sqlSession = sqlSessionFactory.openSession();
            user=sqlSession.selectOne("selectUserPwd",username);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return user.getPassword();
    }
}

pojo类

package com.pojo;

public class User {
    String username;
    String password;

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

(5)搭建tomcat

路径设置为/web,然后点apply

 点击server

 启动tomcat,点击这只小虫子(debug)

 

六、MyBatis中使用接口代理getMapper 

        在mybatis中,有一个方法可以动态的生成mapper接口的实现类,程序员只需要写出mapper接口,SQL映射文件即可,mapper接口的实现类可以让mybatis动态生成。

(1)将mapper实现类删掉

(2)更新Service实现类

package com.service.impl;

import com.mapper.UserMapper;
import com.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;

public class UserServiceImpl implements UserService {

    @Override
    public String selectUserPwd(String username) {
        SqlSession sqlSession = null;
        try {
            //可以将Sqlsession封装成工具类,就不会像下面这么复杂
            sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        return userMapper.selectPwd(username);
    }
}

(3)更新SQL映射文件

<?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.mapper.UserMapper">
    <select id="selectPwd" resultType="String">
        select user_pwd password from t_user where user_name=#{username}
    </select>
</mapper>

 这里的namespace需要写接口的全限定命,select标签的id需要写方法的名字

解释:getmapper()方法底层是采用反射机制

七、MyBatis小技巧

(1)#{}和${}

在以上SQL映射文件中,给参数传值都是采用#{}符号,还有一种是${}。

#{}:先编译sql语句,再给占位符传值,底层是PreparedStatement实现。可以防⽌sql注⼊,⽐较常⽤。

${}:先进⾏sql语句拼接,然后再编译sql语句,底层是Statement实现。存在sql注⼊现象。只有在需要 进⾏sql语句关键字拼接的情况下才会⽤到。

(2)typeAliases

在SQL映射文件中,select标签需要使用resultType来映射结果集,但通常需要写的返回结果集是全限定类名,带有很多包名,可以在核心配置文件中采用以下两种方式解决。

typeAlias
<typeAliases>
        <typeAlias type="com.pojo.User" alias="user"/>
</typeAliases>
type属性:指定给哪个类起别名。
alias属性:别名。
当你写的是user,在SQL映射文件中不区分大小写,你可以写User、USER、user等
可以写多个typeAlias标签

package

<typeAliases>
        <package name="com.pojo"/>
</typeAliases>

当你有一百个类名时,需要写一百个typeAlias,这时可以采用package

在pojo包中的所有类都会自动起别名,别名就是简名类

(3)mapper

mapper不止有resource、url等属性,还有class、package

class

使用class有两个条件:

        1、接口名字与映射文件名字要保持一致

        2、映射文件与接口要在同一目录

<mappers>
        <mapper class="com.mapper.UserMapper"/>
</mappers>

 package

当有一百个接口,就要写一百个SQL映射文件,这时候就可以用package

条件与class一致

<mappers>
        <package name="com.mapper"/>
</mappers>

八、MyBatis参数处理

(1)通过map集合传参

        写mapper接口方法

package com.mapper;

import java.util.Map;

public interface UserMapper {
    
    //通过map集合传参
    int insertUserMap(Map<String,String> map);
}

        写SQL映射文件

<?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.mapper.UserMapper">

    <insert id="insertUserMap">
        insert into t_user values(null,#{username1},#{password1})
    </insert>
</mapper>

        写service接口方法

package com.service;

import java.util.Map;

public interface UserService {
    
    //通过map添加user
    int insertUser(String username,String password);
}

        service子类实现接口方法

package com.service.impl;

import com.mapper.UserMapper;
import com.service.UserService;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class UserServiceImpl implements UserService {

    @Override
    public int insertUser(String username,String password) {
        SqlSession sqlSession = null;
        try {
            //可以将Sqlsession封装成工具类,就不会像下面这么复杂
            sqlSession = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String,String> map = new HashMap<>();
        map.put("username1",username);
        map.put("password1",password);
        int count = mapper.insertUserMap(map);
        sqlSession.commit();
        return count;
    }
}

        写控制层get方法

package com.controller;

import com.service.UserService;
import com.service.impl.UserServiceImpl;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/first")
public class controller extends HttpServlet {

    UserService userService = new UserServiceImpl();

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        //获取用户名字
        String username = request.getParameter("username1");
        String password = request.getParameter("password1");
        int count = userService.insertUser(username, password);
        if (count==1){
            out.print("添加成功");
        }else {
            out.print("添加失败");
        }
    }
}

        写前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>我的第一个web项目-mybatis</title>
</head>
<script type="text/javascript">
    window.onload=function () {
        document.getElementById("btn1").onclick=function () {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange=function () {
                if (xhr.readyState == 4) {
                    if (xhr.status >= 200 && xhr.status < 300) {
                        alert(xhr.responseText)
                    }
                }
            }
            var username1 = document.getElementById("username1").value;
            var password1 = document.getElementById("password1").value;
            xhr.open("get","/web/first?username1="+username1+"&password1="+password1,true)
            xhr.send()
        }
    }
</script>

<body>
    <h2>添加用户</h2>
    请输入要添加的用户名:<input type="text" id="username1"><br>
    请输入要添加的密码:<input type="text" id="password1"><br>
    <input type="button" id="btn1" value="添加">
</body>
</html>

(2)实体类传参

        创建一个pojo类

package com.pojo;

public class User {
    String username;
    String password;

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }
}

        添加mapper接口方法

package com.mapper;

import com.pojo.User;

public interface UserMapper {
    //通过实体类传参
    int insertUserPojo(User user);
}

        添加SQL映射文件

<?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.mapper.UserMapper">

    <insert id="insertUserPojo">
        insert into t_user values(null,#{username},#{password})
    </insert>
</mapper>

(3)@Param注解传参

        添加mapper接口方法

//通过@param注解传参
    List<User> selectUserParam(@Param("name") String username,@Param("pwd") String password);

        添加SQL映射文件

<select id="selectUserParam" resultType="com.pojo.User">
        select user_name username,user_pwd password from t_user where user_name=#{name} and user_pwd=#{pwd}
</select>

九、MyBatis查询语句专题

        通常数据库和java中的映射类起的名字是不一样的,如果不采用as起别名,执行sql语句是无法映射到映射类,这里有三种解决方案:as起别名 、resultMap结果映射、开启驼峰式命名

(1)as起别名

user_name是数据库的命名规范,username是java中的命名规范(其实这里的N应该大写)

所以就会将username映射到User类中

<select id="selectUserParam" resultType="com.pojo.User">
        select user_name username,user_pwd password from t_user where user_name=#{name} and user_pwd=#{pwd}
</select>

(2)使用resultMap结果映射

 可以重复利用,type可以使用别名

<resultMap id="userResultMap" type="com.pojo.User">
     <id property="id" column="id"/>
     <result property="user_name" column="username"/>
     <result property="user_pwd" column="password"/>
</resultMap>

<select id="selectUserResultMap" resultMap="userResultMap">
     select user_name,user_pwd from t_user where user_name=#{username}
</select>

(3)开启驼峰式命名

在mybatis核心配置文件中配置如下,记得写在properties标签下面,没有可不管

<settings>
 <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
实体类中的属性名   对应--->   数据库表的列名
carNum                                       car_num
carType                                       car_type
produceTime                               produce_time

十、MyBatis高级映射及延迟加载

(1)级联属性(了解)

1、创建Student、Clazz类(省略了有参无参构造、getter、setter、toString方法)

public class Student {
 private Integer sid;
 private String sname;
 private Clazz clazz;
}
public class Clazz {
 private Integer cid;
 private String cname;
}

2、写SQL映射文件

<?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.powernode.mybatis.mapper.StudentMapper">
 <resultMap id="studentResultMap" type="Student">
 <id property="sid" column="sid"/>
 <result property="sname" column="sname"/>
 <result property="clazz.cid" column="cid"/>
 <result property="clazz.cname" column="cname"/>
 </resultMap>
 <select id="selectBySid" resultMap="studentResultMap">
 select s.*, c.* from t_student s join t_clazz c on s.cid = c.cid w
here sid = #{sid}
 </select>
</mapper>

3、写测试程序

public class StudentMapperTest {
 @Test
 public void testSelectBySid(){
 StudentMapper mapper = SqlSessionUtil.openSession().getMapper(StudentMapper.class);
 Student student = mapper.selectBySid(1);
 System.out.println(student);
 }
}

4、执行结果 

(2)association

只需要修改association即可,其他地方无需修改

<resultMap id="studentResultMap" type="Student">
 <id property="sid" column="sid"/>
 <result property="sname" column="sname"/>
 <association property="clazz" javaType="Clazz">
 <id property="cid" column="cid"/>
 <result property="cname" column="cname"/>
 </association>
</resultMap>

(3)分布查询 

association中select位置填写sqlId。sqlId=namespace+id。其中column属性作为这条⼦sql语
句的条件
<resultMap id="studentResultMap" type="Student">
 <id property="sid" column="sid"/>
 <result property="sname" column="sname"/>
 <association property="clazz" select="com.powernode.mybatis.mapper.ClazzMapper.selectByCid" column="cid"/>
</resultMap>
<select id="selectBySid" resultMap="studentResultMap">
 select s.* from t_student s where sid = #{sid}
</select>

在ClazzMapper接⼝中添加⽅法

public interface ClazzMapper {
 Clazz selectByCid(Integer cid);
}
在ClazzMapper.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.powernode.mybatis.mapper.ClazzMapper">
 <select id="selectByCid" resultType="Clazz">
 select * from t_clazz where cid = #{cid}
 </select>
</mapper>
执⾏结果,可以很明显看到先后有两条sql语句执⾏:

十一、MyBatis的缓存机制

(1)一级缓存

同一个 SqlSession中,执行两次相同的 sql 语句,
第一次执行完毕会将数据库中查询的数据写到缓存,第二次会直接从缓存中获取,从而提高查询效率。当一个 sqlSession 结束后该 sqlSession 中的 一级缓存也就不存在了。Mybatis 默认开启一级缓存。
 sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存。

手动调用sqlSession . clearCache ()也会清空缓存。

(2)二级缓存

1. <setting name="cacheEnabled" value="true"> 全局性地开启或关闭所有映射器配置⽂件中已配置的任何缓存。默认就是true,⽆需设置。
2. 在需要使⽤⼆级缓存的SqlMapper.xml⽂件中添加配置:<cache />
3. 使⽤⼆级缓存的实体类对象必须是可序列化的,也就是必须实现java.io.Serializable接⼝
4. SqlSession对象关闭或提交之后,⼀级缓存中的数据才会被写⼊到⼆级缓存当中。此时⼆级缓存才可⽤。  
⼆级缓存的失效:只要两次查询之间出现了增删改操作。⼆级缓存就会失效。【⼀级缓存也会失效】

十二、MyBatis逆向工程

(1)第一步

新建module,在pom.xml文件中配置逆向工程插件

<build>
        <!--可配置多个插件-->
        <plugins>
            <!--其中的⼀个插件:mybatis逆向⼯程插件-->
            <plugin>
                <!--插件的GAV坐标-->
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.4.1</version>
                <!--允许覆盖-->
                <configuration>
                    <overwrite>true</overwrite>
                </configuration>
                <!--插件的依赖-->
                <dependencies>
                    <!--mysql驱动依赖-->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.30</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

(2) 第二步

配置generatorConfig.xml,文件名必须为generatorConfig,该文件必须放在类的根目录下
<?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有两个值:
    MyBatis3Simple:⽣成的是基础版,只有基本的增删改查。
    MyBatis3:⽣成的是增强版,除了基本的增删改查之外还有复杂的增删改查。
    -->
    <context id="DB2Tables" targetRuntime="MyBatis3Simple">
        <!--防⽌⽣成重复代码-->
        <plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>

        <commentGenerator>
            <!--是否去掉⽣成⽇期-->
            <property name="suppressDate" value="true"/>
            <!--是否去除注释-->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--连接数据库信息-->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatisfuxi"
                        userId="root"
                        password="123456">
        </jdbcConnection>
        <!-- ⽣成pojo包名和位置 -->
        <javaModelGenerator targetPackage="com.pojo" targetProject="src/main/java">
            <!--是否开启⼦包-->
            <property name="enableSubPackages" value="true"/>
            <!--是否去除字段名的前后空⽩-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- ⽣成SQL映射⽂件的包名和位置 -->
        <sqlMapGenerator targetPackage="com.mapper" targetProject="src/main/resources">
            <!--是否开启⼦包-->
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- ⽣成Mapper接⼝的包名和位置 -->
        <javaClientGenerator
                type="xmlMapper"
                targetPackage="com.mapper"
                targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 表名和对应的实体类名-->
        <table tableName="t_user" domainObjectName="User"/>
    </context>
</generatorConfiguration>

(3)第三步

运行插件(双击) 

成功之后会自动生成项目架构

十三、MyBatis分页查询

(1)limi分页

select
 *
from
 tableName ......
limit
 (pageNum - 1) * pageSize, pageSize
第⼀个数字:startIndex(起始下标。下标从 0 开始。)
第⼆个数字:pageSize(每⻚显示的记录条数)
假设已知⻚码pageNum,还有每⻚显示的记录条数pageSize,第⼀个数字可以动态的获取吗?
startIndex = (pageNum - 1 ) * pageSize

(2)PageHelper插件 

1、引入相关依赖

<dependency>
 <groupId>com.github.pagehelper</groupId>
 <artifactId>pagehelper</artifactId>
 <version>5.3.1</version>
</dependency>

2、配置mybatis-config文件

typeAliases标签中配置

<plugins>
 <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

3、编写java代码

接口:

List<Car> selectAll();

SQL映射文件

<select id="selectAll" resultType="Car">
 select * from t_car
</select>
在查询语句之前开启分⻚功能。
在查询语句之后封装PageInfo对象。(PageInfo对象将来会存储到request域当中。在⻚⾯上展
示。)
@Test
public void testPageHelper() throws Exception{
 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
 SqlSession sqlSession = sqlSessionFactory.openSession();
 CarMapper mapper = sqlSession.getMapper(CarMapper.class);
 // 开启分⻚
 PageHelper.startPage(2, 2);
 // 执⾏查询语句
 List<Car> cars = mapper.selectAll();
 // 获取分⻚信息对象
 PageInfo<Car> pageInfo = new PageInfo<>(cars, 5);
 System.out.println(pageInfo);
}

十四、MyBatis注解开发

mybatis中也提供了注解开发方式,采用注解方式可以减少SQL映射文件的配置

在官方文档中,建议用注解来映射简单的SQL语句,对于复杂的SQL语句,会让你本来就复杂的SQL语句变得更加复杂,所以如果你需要做一些复杂的操作,建议采用XML来映射语句

(1)@insert

public interface CarMapper {
        @Insert(value="insert into t_car values(null,#{carNum},#{brand},#{guidePrice},#{produceTime},#{carType})")
        int insert(Car car);
}
@Test
public void testInsert() throws Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(null, "1112", "卡罗拉", 30.0, "2000-10-10", "燃油⻋");
        int count = mapper.insert(car);
        System.out.println("插⼊了⼏条记录:" + count);
        sqlSession.commit();
        sqlSession.close();
}

(2)@delete

@Delete("delete from t_car where id = #{id}")
int deleteById(Long id);
@Test
public void testDelete() throws Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().bu
        ild(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        mapper.deleteById(89L);
        sqlSession.commit();
        sqlSession.close();
}

(3)@Update

@Update("update t_car set car_num=#{carNum},brand=#{brand},guide_price=#{gu
idePrice},produce_time=#{produceTime},car_type=#{carType} where id=#{id}")
int update(Car car);
@Test
public void testUpdate() throws Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().b
        uild(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(88L,"1001", "凯美瑞", 30.0,"2000-11-11", "新能源");
        mapper.update(car);
        sqlSession.commit();
        sqlSession.close();
}

(4)@Select

@Select("select * from t_car where id = #{id}")
@Results({
 @Result(column = "id", property = "id", id = true),
 @Result(column = "car_num", property = "carNum"),
 @Result(column = "brand", property = "brand"),
 @Result(column = "guide_price", property = "guidePrice"),
 @Result(column = "produce_time", property = "produceTime"),
 @Result(column = "car_type", property = "carType")
})
Car selectById(Long id);
@Test
public void testSelectById() throws Exception{
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().bu
        ild(Resources.getResourceAsStream("mybatis-config.xml"));
        SqlSession sqlSession = sqlSessionFactory.openSession();
        CarMapper carMapper = sqlSession.getMapper(CarMapper.class);
        Car car = carMapper.selectById(88L);
        System.out.println(car);
}

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值