MyBatis是什么?使用它作为持久层框架有什么优点?

MyBatis:简化数据库操作的持久层框架 MyBatis 是一个基于 Java 的持久层框架,起源于 Apache 的 iBatis 项目,后迁移至 Google Code 并更名为 MyBatis,最终在 2013 年迁移到 GitHub。它支持自定义 SQL、存储过程和高级映射,简化了 JDBC 操作,通过 XML 或注解配置实现 Java 对象与数据库记录的映射。MyBatis 的优点包括简化数据库操作、灵活的 SQL 控制、高度可定制化、轻量级和优秀的性能,但也存在配置繁琐、SQL 维护复杂、缺乏全面 ORM 支持等缺点。与 Hiberna 阅读详情


一、前言

在阅读本篇文章之前,我先提问一下:

  • mybatis映射文件、核心配置文件、properties配置文件、日志文件到底在这个框架中各自的功能是什么?它们在文件夹中的位置该如何设定?
  • resultMap、resultType有什么不同?什么时候要使用它们?
  • 遇到像模糊查询时,我们该如何正确操作?
  • {} 、${} 之间的区别是什么?各自使用的情景是什么?

  • mybatis缓存是什么?
  • 分步查询会不会?
  • ...

废话不多说,满满的干货,赶快来看看吧~

二、基本介绍

一句话总结一下,MyBatis是一个基于Java的持久层框架,是一个半自动的ORM框架。那么可爱的它具有哪些很好的特性呢?

  • 支持定制化 SQL、存储过程以及高级映射
  • 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的操作
  • 可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(实体类)映射成数据库中的记录

那么它有哪些优点呢?

  • 轻量级,性能出色
  • SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据

好了,了解这些就差不多了,接下来进入Mybatis的知识世界!

三、搭建开发环境

首先要做的就是引入依赖,具体的pom.xml如下:

  <packaging>jar</packaging>
    <dependencies> <!-- Mybatis核心 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency> <!-- junit测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency> <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency><!-- log4j日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

这里需要注意的就是MySQL的驱动依赖了,我直接跟着视频走,使用的是版本5.7,结果可想而知,报错了,呜呜呜~

接着就是创建实体类、mapper接口、核心配置文件、映射文件,我给大家依次演示一下如何使用:

实体类:与数据库字段相关联,这个数据库在我的石墨文档第一个位置,大家可以自己运行一下SQL代码试一试

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String sex;
    private String email;
}

mapper接口:可以从官方文档中找案例复制下来——Mybatis官方文档

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

核心配置文件:跟mapper接口一样,也可以从官方中复制下来

<?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"/>
    <typeAliases>
        <package name="com.cabbage.pojo"/>
    </typeAliases>
    <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.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--<mapper resource="mappers/UserMapper.xml"/>-->
        <package name="com.cabbage.mappers"/>
    </mappers>
</configuration>

最后再来一个日记文件记录信息以及jdbc.properties配置文件

日志文件:可以当做是一种模板

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <param name="Encoding" value="UTF-8"/>
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n"/>
        </layout>
    </appender>
    <logger name="java.sql">
        <level value="debug"/>
    </logger>
    <logger name="org.apache.ibatis">
        <level value="info"/>
    </logger>
    <root>
        <level value="debug"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

jdbc.properties配置文件:配置数据库的连接信息——用户名、密码等等

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

说了这么多配置文件,大家估计都懵了,这些文件各自放在什么目录下呢?大家可以参考一下我的位置

好了,各位小伙伴们,基本的环境搭建已经完成了,熟悉mybatis的小伙伴们看到这些文件中的属性,也知道各自是什么功能;不知道的小伙伴也不要着急,从案例中慢慢就会解密他们的各自功能以及使用方法。

四、核心配置文件

让我们回过头来看看刚才搭建的核心配置文件,如何使用?

  • 1、<properties/>

  • 2、<typeAliases></typeAliases>

  • 3、<mappers></mappers>

    需要特别注意的是:在resources文件夹下建包时,格式应该是下图的样式

五、mapper映射文件

先看一下映射文件的命名规则:

  • 表所对应的实体类的类名+Mapper.xml

例如:表t_user,映射的实体类为User,所对应的映射文件为UserMapper.xml 因此一个映射文件对应一个实体类,对应一张表的操作

  • MyBatis映射文件用于编写SQL,访问以及操作表中的数据
  • MyBatis映射文件存放的位置是src/main/resources/mappers目录下

此外,MyBatis中可以面向接口操作数据,要保证两个一致:

  • mapper接口的全类名和映射文件的命名空间(namespace)保持一致
  • mapper接口中方法的方法名和映射文件中编写SQL的标签的id属性保持一致

写一个代码演示一下:查询表中id=3的user

    <!--User selectById();-->
    <select id="selectById" resultType="User">
        SELECT * FROM t_user WHERE id = 3
    </select>

public interface UserMapper {
    User selectById();
}

运行结果完全正确:

需要注意的是:

  • 查询的标签select必须设置属性resultType或resultMap,用于设置实体类和数据库表的映射
  • resultType:自动映射,用于属性名和表中字段名一致的情况
  • resultMap:自定义映射,用于一对多或多对一或字段名和属性名不一致的情况,这个后面就会讲到
  • 当查询的数据为多条时,不能使用实体类作为返回值,只能使用集合,否则会抛出异常TooManyResultsException;但是若查询的数据只有一条,可以使用实体类或集合作为返回值

六、参数值的两种方式(重点)

  • MyBatis获取参数值的两种方式:${}和#{}

  • ${}的本质就是字符串拼接,#{}的本质就是占位符赋值

  • ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号

在学习中,原本把参数值分为五种情况,最后介绍了注解@Param的使用,最后就把这五种情况归纳为两种情况,那就来介绍这两种情况吧!

  • 1、实体类类型参数
  • 2、使用@Param标识参数,使用该注解时,以@Param注解的值为键,以参数为值,或者以param1、param2为键,以参数为值

下面找一些具有代表性的代码,方便以后的回忆,小伙伴们也可以看看这些代码是否还知道是什么意思呀,测试代码就不写了

七、select的重点介绍

    查询单个数据,这个很简单了
    <!--Integer getCount();-->
    <select id="getCount" resultType="integer">
        select count(*) from t_user
    </select>

    查询一条数据为map集合,会把查询到的一个对象封装在map中
    <!--Map<String,Object> getUserByIdToMap(@Param("id") Integer id);-->
    <select id="getUserByIdToMap" resultType="map">
        select * from t_user where id = #{id}
    </select>

    查询所有数据放入到map集合中
//方式一:    List<Map<String,Object>> getAllUsersToMap();
    @MapKey("id"),<!--把id当做map的键,查询的对象作为值返回过来-->
    Map<String, Object> getAllUsersToMap();

对查询所有数据放入到map集合中这种方式,进行代码测试一下:

    @Test
    public void test4() throws IOException {
        SqlSession sqlSession = GetSqlSession.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        List<Map<String, Object>> mapList = mapper.getAllUsersToMap();
        Map<String, Object> map = mapper.getAllUsersToMap();
//        System.out.println(mapList);
        System.out.println(map);
    }

看一下查询的部分结果:

八、特殊SQL的查询

  • 1、模糊查询
    <!--List<User> getUserByLike(@Param("username") String username);-->
    <select id="getUserByLike" resultType="User">
        select * from t_user where username like "%"#{username}"%"
    </select>

  • 2、批量删除
    <!--Integer deleteMore(@Param("ids") String ids);-->
    <delete id="deleteMore">
        delete from t_user where id in (${ids})
    </delete>

代码演示一下:

    @Test
    public void test2() throws IOException {
        SqlSession sqlSession = GetSqlSession.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        Integer result = mapper.deleteMore("7,8,9");
        System.out.println(result);
    }
复制代码

运行结果: [图片上传失败...(image-4c6888-1659663334477)]

  • 3、动态设置表名
    <!--List<User> getAllUserByTableName(@Param("tableName") String tableName);-->
    <select id="getAllUserByTableName" resultType="User">
        select * from ${tableName}
    </select>

  • 4、添加功能获取自增的主键
    <!--int insertUser(User user);
    useGeneratedKeys:设置使用自增的主键 
    keyProperty:因为增删改有统一的返回值是受影响的行数,
    因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
-->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email})
    </insert>
    <!--这句话是什么意思呢?也就是说加入一个user对象的同时
    ,把该对象的自增键的值赋给id,通过调用getter方法拿到id值-->

代码演示一下:

    @Test
    public void test4() throws IOException {
        SqlSession sqlSession = GetSqlSession.getSqlSession();
        SQLMapper mapper = sqlSession.getMapper(SQLMapper.class);
        User user = new User(null, "cabbage8"
                , "123454", 23, "男"
                , "cabbage8@qq.com");
        int result = mapper.insertUser(user);
        System.out.println(result);
        System.out.println(user.getId());
    }

运行结果:

九、自定义resultMap

  • 1、resultMap处理字段和属性的映射关系,若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射
    <resultMap id="mapEmp" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
    </resultMap>
    <!--List<Emp> getAllEmp();-->
    <select id="getAllEmp" resultMap="mapEmp">
        select eid,emp_name,age,sex,email,did from t_emp
--或者select eid,emp_name empName,age,sex,email,did from t_emp
    </select>

resultMap:设置自定义映射属性:

  • id:表示自定义映射的唯一标识
  • type:查询的数据要映射的实体类的类型子标签:
  • id:设置主键的映射关系

result:设置普通字段的映射关系

  • property:设置映射关系中实体类中的属性名
  • column:设置映射关系中表中的字段名

当然,若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用),实体类中的属性名符合Java的规则(使用驼峰)时,可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,在查询表中数据时,自动将类型的字段名转换为驼峰 例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName

  • 2、多对一映射处理,这是重点!

我们需要修改一下核心配置文件的内容,添加一些配置(这些配置在官方文档中都有介绍):

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--开启延迟加载-->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>

三种方式的介绍:

    <!--Emp getEmpAndDept(@Param("eid") Integer eid);-->
    <!--方式一:级联属性赋值-->
    <resultMap id="getEmpAndDeptMap1" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <result property="dept.did" column="did"/>
        <result property="dept.deptName" column="dept_name"/>
    </resultMap>
    <!--方式二:association解决映射关系-->
    <resultMap id="getEmpAndDeptMap2" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <association property="dept" javaType="Dept">
            <result property="did" column="did"/>
            <result property="deptName" column="dept_name"/>
        </association>
    </resultMap>
    <!--方式三:分步查询-->
    <!--
    select:设置分步查询的SQL的唯一标识(namespace.方法名)
    column:设置分步的查询条件
    fetchType:当开启了全局的延迟加载之后,可通过此属性手动控制延迟加载的效果
    eager,立即加载;lazy,懒加载
    -->
    <resultMap id="getEmpAndDeptByStepMap" type="Emp">
        <id property="eid" column="eid"/>
        <result property="empName" column="emp_name"/>
        <association property="dept"
                     select="com.cabbage.mappers.DeptMapper.getEmpAndDeptByStepTwo"
                     column="did"
                     fetchType="eager">
        </association>
    </resultMap>
    <!--Emp getEmpAndDeptByStepOne(@Param("eid") Integer eid);-->
    <select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepMap">
        select * from t_emp where eid = #{eid}
    </select>

方式三中DeptMapper.xml对应的分步查询的第二步:

    <!--Dept getEmpAndDeptByStepTwo(@Param("did") Integer did);-->
    <select id="getEmpAndDeptByStepTwo" resultType="Dept">
        select * from t_dept where did = #{did}
    </select>

老师说,方式三在实际开发中使用的最多,方式三是一种懒加载,那咱们就测试一下方式三:

    @Test
    public void test3() throws IOException {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.getEmpAndDeptByStepOne(1);
        System.out.println(emp.getEmpName());
        System.out.println("----------------");
        System.out.println(emp.getDept());
    }

运行结果:

我们把eager改成lazy后的运行结果:

  • 3、一对多映射处理,这是重点!
    <!--方式一:
    collection:处理一对多的映射关系
    ofType:表示该属性所对应的集合中存储数据的类型
    -->
    <resultMap id="getDeptAndEmpMap" type="Dept">
        <result property="did" column="did"></result>
        <result property="deptName" column="dept_name"></result>
        <collection property="emps" ofType="Emp">
            <result property="eid" column="eid"></result>
            <result property="empName" column="emp_name"></result>
            <result property="age" column="age"></result>
            <result property="email" column="email"></result>
            <result property="sex" column="sex"></result>
            <result property="did" column="did"></result>
        </collection>
    </resultMap>
    <!--Dept getDeptAndEmp(@Param("did") Integer did);-->
    <select id="getDeptAndEmp" resultMap="getDeptAndEmpMap">
        select * from t_dept t1 left join t_emp t2 on t1.did = t2.did where t1.did = #{did}
    </select>

    <!--方式二-->
    <resultMap id="getDeptAndEmpOneMap" type="Dept">
        <id property="did" column="did"></id>
        <result property="deptName" column="dept_name"></result>
        <collection property="emps"
                    select="com.cabbage.mappers.EmpMapper.getDeptAndEmpByStepTwo"
                    column="did">
        </collection>
    </resultMap>
    <!-- Dept getDeptAndEmpOne(@Param("did") Integer did);-->
    <select id="getDeptAndEmpOne" resultMap="getDeptAndEmpOneMap">
        select * from t_dept where did = #{did}
    </select>

方式二中EmpMapper.xml对应的分步查询的第二步:

    <!--List<Emp> getDeptAndEmpByStepTwo(@Param("eid") Integer eid);-->
    <select id="getDeptAndEmpByStepTwo" resultType="Emp">
        select * from t_emp where did= #{eid}
    </select>

写个测试代码:

    @Test
    public void test4() throws IOException {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        Dept dept = mapper.getDeptAndEmpOne(1);
        System.out.println(dept);
    }

十、动态SQL

Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。接下来就为大家逐一介绍他们的使用代码

  • 1、if的使用:if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;反之标签中的内容不会执行
    <!--List<User> getUserByCondition(User user);-->
    <select id="getUserByCondition" resultType="User">
        select * from t_user where 1=1
        <if test="username !=null and username != ''">
            and username = #{username}
        </if>
        <if test="password != null and password != ''">
            and password = #{password}
        </if>
    </select>\

这个语句是什么意思呢?其实就是我们传入一个实体对象,对象的username、password属性不为空或者不为null,就查询。对应的SQL语句是:select * from t_user where 1=1 and username = ? and password = ?

  • 2、where的使用
<!--List<User> getUserByWhere(User user);-->
    <select id="getUserByWhere" resultType="User">
        select * from t_user
        <where>
            <if test="username != null and username != ''">
                and username = #{username}
            </if>
            <if test="password != null and password != ''">
                and password = #{password}
            </if>
        </where>
    </select>
\

where和if一般结合使用: 1、若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字 2、若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的 and去掉 3、注意:where标签不能去掉条件最后多余的and

  • 3、trim的使用
<!--List<User> getUserByTrim(User user);-->
    <select id="getUserByTrim" resultType="User">
        select * from t_user
        <trim prefix="where" suffixOverrides="and">
            <if test="username != null and username != ''">
                username = #{username} and
            </if>
            <if test="password != null and password != ''">
                password = #{password} and
            </if>
        </trim>
    </select>
\\\

trim用于去掉或添加标签中的内容,常用属性: 1、prefix:在trim标签中的内容的前面添加某些内容 2、prefixOverrides:在trim标签中的内容的前面去掉某些内容 3、suffix:在trim标签中的内容的后面添加某些内容 4、suffixOverrides:在trim标签中的内容的后面去掉某些内容

  • 4、choose、when、otherwise的使用,相当于if...else if..else,满足一个if条件就不会执行下一个条件了
    <!--List<User> getUserByIfElse(User user);-->
    <select id="getUserByIfElse" resultType="User">
        select * from t_user
        <where>
            <choose>
                <when test="username != null and username != ''">
                    username = #{username}
                </when>
                <when test="password != null and password != ''">
                    password = #{password}
                </when>
                <otherwise>
                    id = 3
                </otherwise>
            </choose>
        </where>
    </select>
  • 5、foreach的使用
<!--int insertByForeach(@Param("users") List<User> list);-->
    <insert id="insertByForeach">
        insert into t_user values
        <foreach collection="users" item="item" separator=",">
            (null,#{item.username},#{item.password},#{item.age},#{item.sex},#{item.email})
        </foreach>
    </insert>
<!--对应的SQL语句就是:insert into t_user values (null,?,?,?,?,?) , (null,?,?,?,?,?)-->

    <!--int deleteByForeach(@Param("id") int[] id);-->
    <delete id="deleteByForeach">
        delete from t_user where id in
        <foreach collection="id" open="(" close=")" separator="," item="item">
            #{item}
        </foreach>
    </delete>
<!--对应的SQL语句是:delete from t_user where id in ( ? , ? )-->

一起来看看其中的属性: 1、collection:设置要循环的数组或集合 2、item:表示集合或数组中的每一个数据 3、separator:设置循环体之间的分隔符 4、open:设置foreach标签中的内容的开始符 5、close:设置foreach标签中的内容的结束符

  • 6、SQL片段的使用,可以记录一段公共sql片段,在使用的地方通过include标签进行引入
    <sql id="selectAll">
        id,username,password,age,sex,email
    </sql>
<!--比如我们把select * 这个查询字段可以改为表中所有的字段到sql片段中,
最后再把 *去掉,引入sql片段就可以了-->

    select <include refid="selectAll"></include> from t_user

十一、MyBatis的缓存

对于这一部分的讲解,我不打算举例代码,因为相信学过mybatis的小伙伴们,看看对缓存的文字介绍,就可以回想起缓存所具有的特点,那么咱们就先从一级缓存开始吧!

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。把握两点:一是同一个sqlsession,二是查询相同的数据。缓存影响着我们的查询速度,但不影响我的查询数据!

使一级缓存失效的四种情况:

  • 不同的SqlSession对应不同的一级缓存
  • 同一个SqlSession但是查询条件不同
  • 同一个SqlSession两次查询期间执行了任何一次增删改操作(注意一下)
  • 同一个SqlSession查询期间手动清空了缓存(sqlSession.clearCache();)

还是演示一下手动清空缓存的情况吧:

    @Test
    public void test1() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = factoryBuilder.build(inputStream);
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        UserMapper mapper1 = sqlSession.getMapper(UserMapper.class);
        User user = mapper.selectById(1);
        sqlSession.clearCache();
        User user1 = mapper1.selectById(1);
        System.out.println(user);
        System.out.println(user1);
    }

运行结果:

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件:

  • 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
  • 在映射文件中设置标签<cache />
  • 二级缓存必须在SqlSession关闭或提交之后有效(不要忘记了哦)
  • 查询的数据所转换的实体类类型必须实现序列化的接口(implements Serializable)

使二级缓存失效的情况:

  • 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

演示一下二级缓存:

 @Test
    public void test2() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = factoryBuilder.build(inputStream);
        SqlSession sqlSession = factory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.selectById(1);
        System.out.println(user1);
        sqlSession.close();//关闭一个后,放入了二级缓存中
        SqlSession sqlSession1 = factory.openSession(true);
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user = mapper1.selectById(1);
        System.out.println(user);
        sqlSession1.close();
    }

运行结果:

二级缓存的相关配置,这一部分老师没有细讲,摘录下来,了解一下。在mapper配置文件中添加的cache标签可以设置一些属性:

  • eviction属性:缓存回收策略 LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。 FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。 SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。 WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。 默认的是 LRU。
  • flushInterval属性:刷新间隔,单位毫秒,默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
  • size属性:引用数目,正整数代表缓存最多可以存储多少个对象,太大容易导致内存溢出
  • readOnly属性:只读,true/false true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。 false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

最后来讲一讲MyBatis缓存查询的顺序:

  • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
  • 如果二级缓存没有命中,再查询一级缓存
  • 如果一级缓存也没有命中,则查询数据库SqlSession关闭之后,一级缓存中的数据会写入二级缓存

十二、创建逆向工程

什么是逆向工程呢?就是先创建数据库表,由框架负责根据数据库表,反向生成如下资源:

  • Java实体类、mapper接口、mapper映射文件

那么就开始根据步骤创建逆向工程吧!

首先需要添加依赖和插件,这里有些依赖使用已经在前面使用过了,大家可以注意一下哦

<!-- 依赖MyBatis核心包 -->
    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.10</version>
        </dependency>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <!-- junit测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies> <!-- 控制Maven在构建过程中相关配置 -->
    <build> <!-- 构建过程中用到的插件 -->
        <plugins> <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.0</version> <!-- 插件的依赖 -->
                <dependencies> <!-- 逆向工程的核心依赖 -->
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency> <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.2</version>
                    </dependency>
                    <!-- MySQL驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.28</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

接着创建MyBatis的核心配置文件以及逆向工程的配置文件,第一个配置文件已经讲过了,来看看逆向工程配置文件如何创建(使用时,发现实体类属性值补全,后来完善了一下视频中的笔记,加了一个配置):

<?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:
    生成基本的CRUD(清新简洁版)
    MyBatis3: 生成带条件的CRUD(奢华尊享版) -->
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!-- 数据库的连接信息 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis"
                        userId="root" password="">
                        <!-- 解决table schema中有多个重名的表生成表结构不一致问题 -->
            <property name="nullCatalogMeansCurrent" value="true"/>
            </jdbcConnection>
        <!-- javaBean的生成策略-->
        <javaModelGenerator targetPackage="com.cabbage.pojo" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- SQL映射文件的生成策略 -->
        <sqlMapGenerator targetPackage="com.cabbage.mappers" targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- Mapper接口的生成策略 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.cabbage.mappers"
                             targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 逆向分析的表 --> <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
        <!-- domainObjectName属性指定生成出来的实体类的类名 -->
        <table tableName="t_user" domainObjectName="User"/>
    </context>
</generatorConfiguration>

需要注意的是:逆向工程配置文件的数据库相关的信息还是需要自己修改配置的

最后执行插件,如图所示:

使用逆向工程生成的目录给大家看一下,可以看出跟我们自己手动创建的一模一样,是不是很简便呢?

好了,本文对MyBatis的知识总结就到这里了,在复习的过程中,对使用逆向工程后的方法没有具体举例介绍,因为方法实在是太多了;还有一个知识点就是分页插件的使用也没有在本文中介绍,原因也是提供的方法很多,不方便介绍,自己认为最好的办法就是找一个小项目,在实际开发中慢慢熟练使用这些框架给的方法!

相关推荐

编写用户帮助/操作手册指南

一个新系统,需要写用户操作手册,该从何下笔?本篇是一篇教你编写用户帮助/操作手册的指南~

pytester的博客 3万+

使用MyBatis的好处

3. MyBatis灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,可重用。1. SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。5. 提供映射标签,支持对象与数据库的ORM字段关系映射(在XML中配置映射关系,也可以使用注解)。对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。1. 与JDBC相比,减少了50%以上的代码量。...

web18536564348的博客 8022

【学习体会】Lighttools8.4.0:矩形阵列光源+条形光源的光学仿真分析

在solidworks中设计了条形光源的基本结构: 由32*6个矩形led组成矩形光源阵列,如下所示 另存为step文件后,导入lighttools中,这里要设置模型的光学属性为:吸收体(机械) 因为我们设计的光源模型是一个整体,我们不能单个面的设置光源,比如说, 这样做的话并不会是这个面设置为光源,而是会把做一个模型都变成一个光源,如下 这显然不是我们想要的 那么,我们就在led位置上放置一个矩形面光源, 这样我们就放置好了一个面光源, 但是问题是,还有191...

LeonJin的博客 1万+

java第七章jdbc课后简答题_Java周测题08.13

1.关于Mybatis的描述正确的是:Mybatis是持久层框架,Mybatis封装了JDBC,Mybatis简化了代码的编辑和使用,Mybatis是一个半ORM(对象关系映射)框架,Mybatis采用了OCP(对象关系映射)的方式封装了数据 错误Mybatis采用的是ORM(对象关系映射)的方式封装数据,不是OCP2.关于JDBC的缺点描述缺点是:每次操作数据时,都需要频繁的开关连接///...

weixin_39850062的博客 769

论文理解【LLM-OR】—— 【PaMOP】Guiding Large Language Models in Modeling Optimization Problem

针对 LLM 求解运筹优化任务,PaMOP 通过约束划分树分离子问题,实现复杂优化问题的分块建模,并结合求解器反馈与反向翻译一致性检查迭代纠错,降低子任务复杂度,提升可执行率与建模准确性。

佚失的诗篇 1007

Qt —— 调用海康C++版SDK获取摄像头每帧图像,通过OpenCv处理每帧图像后显示在Qt窗口(附:源码)

  关注 笔者 - jxd 微信公众号搜索 “码农总动员” 或 微信扫描下方二维码,了解更多你不知道的XX,O(∩_∩)O

5447

Mybatis介绍

一.Mybatis简介? 1.什么是Mybatis? MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。 Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement

weixin_42408447的博客 8623

ADS基础教程19 - 电磁仿真(EM)基本概念和实操

一、引言二、基本概念1.EM介绍2.Momentum介绍3.FEM介绍4.Substrate介绍三、创建Layout并进行Momentum仿真1.创建Layout2.添加Microtrip(微带线)3.添加Substrate4.Momentum仿真四、总结EM全称Electromagnetic,即electro(电)magnetic(磁)。ADS为设计和评估现代通信系统产品提供了电磁仿真工具(EM)。EM包括Momentumsimulator(动量仿真器)和FEM。

XZ_ZC的博客 1万+

MyBatis学习笔记-阶段一

MyBatis简介 MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程 进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。 原理:Mybatis 通过 l xml 或注解的方式将要执行的各种 statement(statement、preparedS...

cyh0503的博客 893

自然语言处理在智能客服系统中的应用

引言与背景 1.1 书籍的目的和内容概述 《自然语言处理在智能客服系统中的应用》旨在探讨自然语言处理(NLP)技术在智能客服系统中的应用,帮助读者理解NLP的核心概念及其在解决实际业务问题中的关键作用。随着人工智能技术的快速发展,自然语言处理成为构建智能客服系统的核心模块之一。本书将深入解析NLP

AI天才研究院 966

HX711重量传感器原理图设计,已量产(压力传感器)

最近调通了一款针对家用、物联网场景的重量传感套件,核心用了 HX711 这颗经典的称重 AD 芯片,还加了用户最需要的 “一键校准” 功能 —— 之前帮朋友做家用米桶余量报警时,用户总吐槽校准步骤太繁琐,这次的方案把操作简化到只按一个键,试下来体验好了不少。正好拆解下这套硬件的设计逻辑,供做同类产品的朋友参考。

不脱发的程序猿 368

什么是 MyBatis?有哪些优点和缺点?

整个架构设计中,SqlMapConfig 和 SqlMap 扮演了连接 DAO 层和数据库的桥梁,定义了 SQL 语句以及参数和结果的映射关系,提供了灵活的数据访问方式。4. IBatis Dao Layer:IBatis Dao 层是 DAO 接口的实现类,它实现了 DAO 接口中的方法,并使用 SqlMap 中定义的 SQL 语句与数据库进行交互。总体来说,MyBatis 是一款成熟且稳定的持久化框架,具有许多优点,且在大型系统中表现良好,但也需要开发者有一定的 SQL 技能和编程经验。

luoluoal的博客 2481

基于Lumerical的1550 nm InGaAs/InP与InGaAs/InAlAs APD设计与功率饱和度优化

摘要 本研究利用Ansys Lumerical软件对1550 nm激光雷达应用的InGaAs/InP和InGaAs/InAlAs雪崩光电二极管(APD)进行仿真设计与优化。通过FDTD光学仿真获取光吸收分布,结合CHARGE模块的电学仿真分析暗电流、光电流及雪崩增益特性。重点研究了两种材料体系的性能差异,并针对近距离强反射导致的功率饱和问题提出结构优化方案。仿真结果表明,InGaAs/InAlAs APD具有更优的过量噪声特性,而优化的电荷层设计可显著提升器件的功率饱和阈值。研究提供了完整的仿真流程与代码实

huanghm88的专栏 97

什么是MyBatis?

MyBatis是一款优秀的持久层框架,用于简化Java应用程序对数据库的操作。它曾是Apache的一个开源项目,名为iBatis,2010年迁移到Google Code并改名为MyBatis,2013年11月又迁移到了GitHub。

2403_86822198的博客 819

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

使用Mybatis连接Mysql数据库

MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML格式或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。优点:1、简单易学:本身就很小且简单。

M11031211的博客 2127

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

MyBatis总结

一、简介 什么是MyBatis? 持久化 持久层 什么是持久层? 为什么需要Mybatis MyBatis的优点 二、入门 安装 从 XML 中构建 SqlSessionFactory 不使用 XML 构建 SqlSessionFactory 从 SqlSessionFactory 中获取 SqlSession 探究已映射的 SQL 语句 提示对命名空间的一点补充 作用域(Scope)和生命周期 提示对象生命周期和依赖注入框架 SqlSessionFactoryBuild

哥的时代,为你保驾护航 186

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

深入浅出 MyBatis | Mybatis 简洁、第一个Mybatis程序

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

青年有志 1058

Mybatis简介

写在最前面,学习Mybatis最好还是从官网入手,多看看官方文档。链接如下:Mybatis中文官方手册 文章目录Mybatis简介1 什么是Mybatis?2 如何获得Mybatis?3 持久化4 持久层5 为什么使用Mybatis? Mybatis简介 1 什么是Mybatis? MyBatis 是一款优秀的持久层框架。 它支持定制化 SQL、存储过程以及高级映射。 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 MyBatis 可以使用简单的 XML

Kc635908933的博客 224

Mybatis基本使用

MyBatis是一个优秀的持久层框架,它对jdbc的操作进行了封装,使得数据库的操作不再繁琐,避免大量的代码编写,使开发人员将更多的精力放在sql语句上。 创建maven项目,并导入依赖 创建实体类 在resources目录下创建mybatis-config.xml 创建一个用于获取SqlSession的工具类 创建Dao层的接口类 创建Mapper层的映射文件UesrMapper.xml(等效于接口实现类) 修改之前的mybatis-config.xml文件 在配置文件中配置Mapper的路径

ufosuai555的博客 1149

Mybatis框架(一)初识Mybatis框架

一、 什么是框架框架(Framework)就是一个提供了可重用的公共结构的半成品,是应用程序的骨架。它就好比建筑物的骨架,结构统一固定,不需要考虑建筑物结构怎么设计,只需要考虑在这样的结构基础上,使用什么内容(建筑材料)来填充这个建筑物。对应到程序上也是一样的道理,程序结构固定,只需填充满足功能的相关代码即可。那么使用框架有什么优势呢?1、 保证了程序结构风格统一,便于学习和维护。2、 省去...

blo1724的博客 313

Mybatis 入门

1. 数据库连接使用时就创建,不使用时便立即释放,从而对数据库进行频繁的操作,导致资源的浪 费、影响性能。优化设想:使用数据库连接池管理数据库对象。2. sql都是硬编码到Java程序中,如果改变sql,那么得重新编译Java代码,不利于系统后期的维护。优化设想:将sql语句配置在xml中,即使改变sql也不用重新编译源代码。3. 向PreparedStatement设置参数,也是硬编码到Java程序中,不利于后期的维护。

m0_74075467的博客 897

Mybatis简介和优缺点

一、什么是Mybatis? Mybatis是一个半自动的ORM持久层框架,内部封装了JDBC。作为开发者只需要关注sql语句本身。Mybatis是通过xml或注解的方式将需要执行的各种statement配置起来。通过Java对象和statement中的sql动态参数映射生成最终执行的sql语句,最终由Mabtais框架执行sql并将结果映射为Java对象并返回。MyBatis 支持定制化 SQL...

Lonely passerby 2万+

MyBatis 的优点?

MyBatis 允许开发者完全自定义 SQL 语句、存储过程以及高级映射,可以根据具体的业务需求编写复杂的查询逻辑,相比全自动化的 ORM 框架(如 Hibernate)更具控制力。MyBatis 将 SQL 语句与 Java 代码分离,便于开发者优化 SQL 查询,避免了全自动 ORM 框架可能生成的冗余 SQL,从而提升性能。MyBatis 的 SQL 与代码分离解决了 JDBC 中 SQL 硬编码的问题,同时支持多种数据库也弥补了 JDBC 在移植性上的不足。

qq_63553317的博客 760

MyBatis学习之01MyBatis的第一个程序

MyBatis 使用参考文档:mybatis文档 学习来源:bilibili狂神说 MyBatis第一个程序 环境说明 jdk 8 + MySQL 5.7.19 maven-3.6.1 IDEA 学习前需要掌握: JDBC MySQL Java 基础 Maven Junit 什么是MyBatis MyBatis 是一款优秀的持久层框架 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程 MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接

Coding马+ 182

Mybatis入门01--第一个Mybatis程序

什么是MyBatis MyBatis 是一款优秀的持久层框架 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的过程 MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 实体类 【Plain Old Java Objects,普通的 Java对象】映射成数据库中的记录。 MyBatis 本是apache的一个开源项目ibatis, 2010年这个项目由apache 迁移到了google code,并且改名为MyBatis 。 2013年.

ywm_up 290
上一篇: Spring Cloud Alibaba Sentinel 初体验
下一篇: 如果老师这么讲面向对象,当年我就不会挂科了吧
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值