Java从坚持到精通-MyBatis

目录

1.什么是ORM思想?

2.第一个MyBatis程序

3.MyBatis的事务管理机制

4.MyBatis中的日志框架

5.MyBatis插入对象

6.MyBatis查询操作

7.命名空间的作用

8.数据源的分类

9.properties标签的配置和使用

10.namespace和增删改查标签中的id限定

11.使用面向接口的方式进行CRUD

12.#{}与${}的区别

13.什么时候可以使用${}?

14.如何使用别名

15.实际扫描mapper.xml文件的方式

16.使用自动生成的主键值

17.MyBatis传参时传多个参数的解决方法

18.@MapKey注解的使用

19.结果映射

20.驼峰命名自动映射

21.动态SQL

1.if标签

2.where标签

3.trim标签

4.set标签

5.choose标签

6.foreach标签

7.sql标签与include标签

22.多对一映射方式

1.级联属性的方式

2.使用association标签

3.分步查询

23.什么是延迟加载

24.一对多映射方式

1.使用collection标签

2.分步查询

25.MyBatis中的缓存机制

1.一级缓存

2.一级缓存的失效

3.二级缓存

4.二级缓存的失效

26.逆向工程

27.分页插件

 28.集成日志框架(logback)


1.什么是ORM思想?

O:object,对应jvm中的对象
R:relational,关系型数据库
M:mapping,映射

就是java对象与数据库之间的映射关系,叫做ORM思想。

2.第一个MyBatis程序

1.创建maven项目

2.添加mybatis依赖和mysql驱动依赖,如下:

<dependency>
     <groupId>org.mybatis</groupId>
     <artifactId>mybatis</artifactId>
     <version>3.5.13</version>
</dependency>
<dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>8.0.33</version>
</dependency>

3.在类路径下创建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="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

4.在类的根路径下编写XxxMapper.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="org.mybatis.example.BlogMapper">

    <insert id="insertCar">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (null,'1003','丰田霸道', 30.0 , '2000-10-11','燃油车');
    </insert>

</mapper>

5.在mybatis-config.xml中的mapper标签中指定XxxMapper.xml的路径,如:

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

6.编写java程序,其中sqlSessions是执行sql语句的一个会话对象。

sqlSession怎么获取:通过sqlSessionFactory

sqlSessionFactory怎么获取:通过sqlSessionFactoryBuilder的build方法

7.示例代码如下:

public class MyBatisIntroductionTest {

    public static void main(String[] args) throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

        // 默认从类的根路径查找资源
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);

        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 参数是CarMapper.xml中insert标签的id
        int count = sqlSession.insert("insertCar");

        System.out.println("插入的记录条数" + count);

        // 手动提交
        sqlSession.commit();
    }

}

3.MyBatis的事务管理机制

有两个,在transactionManager标签中指定:

<transactionManager type="JDBC"/>

type可选JDBC和MANAGED

JDBC:mybatis框架自己管理事务,自己采用原生的JDBC代码去管理事务

MANAGED:mybatis不再负责事务的管理,交给其他容器管理如spring。

4.MyBatis中的日志框架

在mybatis-config.xml文件中配置如下即可:

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

默认已经实现了STDOUT_LOGGING(标准日志)

如果没有在这里配置,可以添加别的日志框架依赖,mybatis会自动查找,如添加logback依赖,然后在类路径下添加logback.xml即可,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置文件修改时重新加载,默认true -->
<configuration debug="false">

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder" charset="UTF-8">
            <!-- 输出日志记录格式 -->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--    mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>


    <!-- 日志输出级别,LOGBACK日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR-->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

5.MyBatis插入对象

需要注意,声明的对象属性和数据库里的列名是一一对应的,支持驼峰对应。mapper的xml文件中#{}表示属性占位符,对应java中的属性名。

@Data
@AllArgsConstructor
public class Car {

    private Long id;
    private String carNum;
    private String brand;
    private Double guidePrice;
    private String produceTime;
    private String carType;

}

<insert id="insertCar">
    insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (#{id}, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType});
</insert>

@Test
public void testCarByPojo(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        Car car = new Car(null, "3333", "比亚迪秦", 30.00, "2020-11-11", "新能源");

        int count = sqlSession.insert("insertCar", car);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
}

6.MyBatis查询操作

注意mapper中需要指定返回的结果对象,如:

<select id="selectById" resultType="com.duolaimi.mybatis.pojo.Car">
    select * from t_car where id = #{id}
</select>

查单个或者多个的返回结果类型都是pojo的全限定类名。

7.命名空间的作用

为了防止id的冲突,因为可能存在相同的方法。

8.数据源的分类

mybatis配置了三种数据源分类:

UNPOOLED:不使用数据库连接池技术,每次请求都是创建新的Connection对象
POOLED:使用mybatis自己实现的数据库连接池
JNDI:集成其他第三方的数据库连接池

9.properties标签的配置和使用

新建jdbc.properties放在类路径下,内容如下:

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

在mybatis-config.xml中添加如下配置:

<properties resource="jdbc.properties"/>

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

表示读取类路径下的jdbc.properties文件,并且使用${}匹配properties中的key。

10.namespace和增删改查标签中的id限定

namespace必须是类的全限定类名,标签中的id必须是方法名,这样底层的javassist工具才能定位到mapper中的sql语句。

11.使用面向接口的方式进行CRUD

只需声明好接口,然后在接口中编写方法名,与mapper.xml中的命名空间与id对应上即可,如下:

public interface CarMapper {

    int insert(Car car);

}

<?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.duolaimi.mybatis.mapper.CarMapper">

    <insert id="insert">
        insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (#{id}, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType});
    </insert>

</mapper>


@Test
public void testInsert(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);

        Car car = new Car(null, "4444", "比亚迪秦", 30.00, "2020-11-11", "新能源");
        int insert = mapper.insert(car);
        System.out.println(insert);

        sqlSession.commit();
}

12.#{}与${}的区别

#{}:底层使用PreparedStatement。特点:先进行SQL语句的编译,然后给SQL语句的占位符?传值,可以避免SQL注入的风险。

${}:底层使用Statement。特点:先进行SQL语句的拼接,然后再对SQL语句进行编译,存在SQL注入的风险。

13.什么时候可以使用${}?

执行的sql语句中,变量是表示sql的关键字的时候,只能用${},如传参表示desc或者acs的查询。

传参用于拼接表名的时候,也必须使用${}。

14.如何使用别名

可以在mabatis-config.xml核心配置文件中添加:

<typeAliases>
    <typeAlias type="com.duolaimi.mybatis.pojo.Car" alias="car"/>
</typeAliases>

在mapper文件中指定resultType时,就可以通过alias来获取类的全限定名称。(别名不区分大小写,且alias属性可以省略,如果省略就是类的简名)

或者使用pakage标签,会将指定包下的类全部自动起别名:

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

15.实际扫描mapper.xml文件的方式

一般情况下,我们会使用指定包的方式来确定扫描的mapper.xml的文件路径,如在mybatis-config.xml中配置:

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

但是前提是编译后的xml文件必须和接口文件放在一起,目录结构如下:

16.使用自动生成的主键值

需要在insert标签中加入两个属性,示例如下:

<insert id="insert" useGeneratedKeys="true" keyProperty="id">
    insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values (#{id}, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType});
</insert>

主要属性是:

useGeneratedKeys="true":开启并使用自动生成主键

keyProperty="id":生成的主键值会赋值到的java对象的属性名

17.MyBatis传参时传多个参数的解决方法

如果不通过@Param注解,则底层默认会将第一个参数设置为arg0或者param1,第二个参数设置为arg1或者param2,以此类推。

可以通过@Param("")指定map中的key,在mapper.xml中写指定的key即可。

18.@MapKey注解的使用

放在方法上,比如@MapKey("id")说明返回时,将原来map中的id字段放到新的map中作为key。

19.结果映射

可以使用resultMap标签来定义结果映射,映射java中属性与数据库中列的关系。

<resultMap id="carResultMap" type="car">
    <id property="id" column="id"/>
    <result property="carNum" column="car_num"/>
    <result property="carType" column="car_type"/>
</resultMap>

<select id="selectById" resultMap="carResultMap">
    select * from t_car where id = #{id}
</select>

注意,select标签中需要加上resultMap属性,且该属性值为上面resultMap标签中的id。

id属性最好加上,会提高查询效率。

当属性名与字段名一致时,property标签可以省略。

20.驼峰命名自动映射

可以在mabatis-config.xml核心配置文件中添加如下配置:

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

即可开启驼峰自动映射,默认是false。

21.动态SQL

1.if标签

if标签中必须有test属性,结果为true或者false,如果使用了@Param注解,test中出现的参数可以为@Param中的值,如果是传的POJO参数,则可以传POJO中的属性名。

2.where标签

主要是嵌套if标签,如果其中的if标签都不成立则不会加where语句,并且多个if成立时,会自动去除语句前面的and或or(注意,不能去除写在语句后面的and或or)

3.trim标签

trim标签常用属性:

prefix:加前缀
suffix:加后缀
prefixOverrides:删除前缀
suffixOverrides:删除后缀

4.set标签

主要是嵌套if标签,多条件时会自动去除if标签后面的逗号。

5.choose标签

choose标签里面一般会配合when标签和otherwise标签一起使用,类似if_else的语法,当前面的成立后,下面就不会执行,也就说choose标签中只能有一个成立,例如:

6.foreach标签

可以执行批量操作如in语句。

foreach标签中常用的属性:
collection:传@Param中的值,否则是Array或者arg0
item:每次循环的对象,对应标签体中的对象
seperator:使用的分隔符,通常都是“,”
open:循环开始符号
close:循环结束符号

如果执行的是批量插入,则不需要open和close属性,示例如下:

#{}中需要写item中指定的对象的属性

7.sql标签与include标签

他们主要是为了代码复用,sql标签声明好后,include标签使用refid将sql的id引用过来,达到代码复用。

22.多对一映射方式

1.级联属性的方式

使用resultMap属性,在多的一方的类加入一的一方的类作为属性,然后resultMap中以“.”的方式赋值属性,如下图所示:

2.使用association标签

在resulltMap中使用association标签,指定属性和java对应的类型即可,示例如下:

3.分步查询

先查学生表数据,返回列中包含cid(班级id),让后指定resultMap,再指定association标签,指定班级的查询语句和传入的参数(column)。

具体如下:

优点:

1.复用性增强,可以重复利用
2.可以充分利用他们的延迟加载/懒加载机制

23.什么是延迟加载

延迟加载的核心原理是:用的时候再执行查询语句,不用的时候不查询。

如何开启:在association标签中,添加fetchType属性,设置成lazy。(默认情况未开启)

如果在association标签中定义的延迟加载是局部开启的,如果想要全局开启,则需要在mybatis-conf.xml核心配置文件中定义,如下所示:

如果全局已定义延迟加载,则局部的延迟加载可以去除。

实际开发中都是需要延迟加载的,建议开启全局的延迟加载。如果不希望语句使用延迟加载,则配置fetchType为eager,则全部加载。

24.一对多映射方式

1.使用collection标签

使用resultMap标签,其中使用collection标签,加上ofType属性,用于指定集合中元素的类型。

2.分步查询

类似上面的分步查询,只是里面是集合时用的标签是collect标签,示例如下:

25.MyBatis中的缓存机制

将select语句的查询结果放到缓存(内存)中,下一次还是这条select语句的时候,直接从缓存中取,不再查数据库。一方面是减少了IO,另一方面不再执行繁琐的查找算法,效率大大提升。

1.一级缓存

默认开启,不需要做任何配置,范围是一个sqlSession,也就是说只要是同一个和SqlSession对象执行同一条SQL语句,就会走缓存。

2.一级缓存的失效

在第一次DQL和第二次DQL之间,如果做了以下两种的任意一种,都会清空一级缓存:

1.执行了sqlSession的clearCache()方法,这是手动清空一级缓存
2.执行了DML(增删改)语句,不管是操作哪张表,都会清空一级缓存

3.二级缓存

二级缓存的范围是SqlSessionFactory

使用二级缓存需要具备以下几个条件:
1.<setting name="cacheEnabled" value="true">全局性地开启或关闭所有映射器配置文件中已配置的任何缓存,默认是true,无需配置。
2.在需要使用二级缓存的SqlMapper.xml文件中添加配置:<cache/>
3.使用二级缓存的实体类对象必须是可序列化的,也就是必修实现Serializable接口
4.SqlSession对象关闭或提交后,一级缓存中的数据才会被写入到二级缓存当中,此时二级缓存才可用。

4.二级缓存的失效

在两次查询之间进行了增删改造作,就会失效。

26.逆向工程

1.添加逆向工程插件

<build>
    <plugins>
        <plugin>
            <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.33</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

2.在根路径下新建generatorConfig.xml文件,内容如下:

<?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="MyBatis3">
        <!--防止生成重复代码-->
        <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/duolaimi"
                        userId="root"
                        password="root">
        </jdbcConnection>
        <!-- 生成pojo包名和位置 -->
        <javaModelGenerator targetPackage="com.duolaimi.mybatis.pojo" targetProject="src/main/java">
            <!--是否开启子包-->
            <property name="enableSubPackages" value="true"/>
            <!--是否去除字段名的前后空白-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <!-- 生成SQL映射文件的包名和位置 -->
        <sqlMapGenerator targetPackage="com.duolaimi.mybatis.mapper" targetProject="src/main/resources">
            <!--是否开启子包-->
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- 生成Mapper接口的包名和位置 -->
        <javaClientGenerator
                type="xmlMapper"
                targetPackage="com.duolaimi.mybatis.mapper"
                targetProject="src/main/java">
            <property name="enableSubPackages" value="true"/>
        </javaClientGenerator>
        <!-- 表名和对应的实体类名-->
        <table tableName="t_stu" domainObjectName="Stu"/>
    </context>
</generatorConfiguration>

3.在该文件中修改数据库连接信息,生成的包信息,需要生成的表信息等

4.双击运行插件即可

如果使用增强版,会生成一个XxxExample类,主要是做条件查询对象的,具体用法如下:

StuExample mapper1 = sqlSession.getMapper(StuExample.class);
mapper1.createCriteria().andAgeBetween(...);

27.分页插件

分页插件的使用:

1.引入依赖:

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

2.在mybatis-config.xml核心配置文件中添加拦截器:

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

3.只要在需要分页查询的前面加入以下代码,即可自动分页:

PageHelper.startPage(1,2);

如果想要查看分页数据的详细信息,可以使用PageInfo对象。

List<Car> list = new ArrayList<>();
PageInfo<Car> carPageInfo = new PageInfo<>(list, 3);

 28.集成日志框架(logback)

1.在pom文件中添加logback的依赖坐标:

<dependency>
       <groupId>ch.qos.logback</groupId>
       <artifactId>logback-classic</artifactId>
       <version>1.2.11</version>
</dependency>

2.在类路径下创建logback.xml文件,指定日志输出格式,文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<!-- 配置文件修改时重新加载,默认true -->
<configuration debug="false">

    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder" charset="UTF-8">
            <!-- 输出日志记录格式 -->
            <pattern>[%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <!--    mybatis log configure-->
    <logger name="com.apache.ibatis" level="TRACE"/>
    <logger name="java.sql.Connection" level="DEBUG"/>
    <logger name="java.sql.Statement" level="DEBUG"/>
    <logger name="java.sql.PreparedStatement" level="DEBUG"/>


    <!-- 日志输出级别,LOGBACK日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR-->
    <root level="DEBUG">
        <appender-ref ref="STDOUT"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值