JAVA-011-初识mybatis


1.1初识Mybatis框架

1.1.1 概念

mybatis是一个java编写的持久层orm框架(对象映射框架),以sql语句得到对象,使用ORM实现结果集封装。

1.1.2 使用Mybatis

  1. 创建maven工程并导入坐标
  2. 创建实体类和Mapper的接口
  3. 创建mybatis的主配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置Mysql的环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置连接数据库的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db1" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="Mybatis/IuserMapper.xml" />
</mappers>

</configuration>
  1. 创建映射配置文件
1
2
3
4
5
<mapper namespace="com.Mapper.IUserMapper" >
<select id="findAll" resultType="com.Pojo.User" >
select * from usr
</select>
</mapper>
  • typeAliases 标签

typeAliases类型别名是为java类型设置一个短的名字,存在的意义仅在于用来减少类完全限定名的冗余。java内置内建类型别名它们都不区分大小写,注意对基本类型名称重复采用的特殊命名风格。

1
2
3
<typeAliases>
<typeAlias type="com.Pojo.User" alias="user"/>
</typeAliases>

默认别名为小写

1
2
3
<typeAliases>
<package name="com.Pojo.User"/>
</typeAliases>
  • dataSource 标签
1
2
3
4
5
6
7
<dataSource type="POOLED">
<!--配置连接数据库的四个基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/db1" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>

POOLED方式

​ 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现

UNPOOLED 方式

​ 采用传统的获取连接的方式,虽然也实现javax.sql.DataSource接口,但是并没有使用连接池技术

mappers 属性

1
2
3
<mappers>
<mapper resource="com/ferao/mapper/UserMapper.xml"/>
</mappers>
1
2
3
4
<mappers>
<mapper class="com.ferao.mapper.UserMapper" />
</mappers>

1
2
3
<mappers>
<package name="com.ferao.mapper"></package>
</mappers>

*** PS:***扫描包进行注入绑定方式,接口和它的Mapper配置文件必须同名且接口和它的Mapper配置文件必须在同一个包下

mybatis映射文件

parameterType(输入类型)

可输入的类型有三种:简单类型、pojo对象、pojo包装对象

1)简单类型

2)pojo对象

mybaits使用OGNL表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称

resultType(输出类型)

可输出的类型有四种:返回一般数据类型(单条)、JavaBean 类型(单条)、List类型(多条)、Map类型

resultMap(映射实体类)

数据库字段名和实体类属性不相同时,无法映射到值,输出为Null。这是因为mybatis会根据这些从数据库中查询到的列名,将列名转化为小写(数据库不区分大小写)去对应实体类中查询相应列名的set方法设值,由于找不到setUserName(),所以会返回Null值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!--column不做限制,可以为任意表的字段,而property须为type 定义的pojo属性-->
<resultMap id="" type="">
<!--设置主键时使用,使用此标签配置映射关系(可能不止一个) -->
<id column="" jdbcType="" property="" />
<result column="" jdbcType="" property=""/>

<association property="" javaType="">
<id column="" jdbcType="" property=""/>
<result column="" jdbcType="" property=""/>
</association>

<!-- 集合中的property须为oftype定义的pojo对象的属性-->
<collection property="pojo的集合属性" ofType="集合中的pojo对象">
<id column="集合中pojo对象对应的表的主键字段" jdbcType="字段类型" property="集合中pojo对象的主键属性" />
<result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的pojo对象的属性" />
</collection>
</resultMap>

mybatis动态SQL

动态sql根据不同的条件生成不同的sql语句.所谓的动态sql,本质还是sql语句,只是开发者可以在sql层面,去执行一个逻辑代码。

  • if、where标签语句示例:
1
2
3
4
5
6
7
8
9
10
11
12
<!-- where 元素只会在至少有一个子元素的条件返回sql子句的情况下,才去插入"where" 子句-->
<select id="queryUser" parameterType="map" resultType="user">
select * from usr
<where>
<if test="id != null" >
id =#{id}
</if>
<if test="username != null" >
and username = #{username}
</if>
</where>
</select>
  • choose,when,otherwise标签语句示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!--
有时不想应用到所有的条件语句,而只想从中择其一项,针对这种情况,Mybatis提供了choose元素
它有点像java中的switch语句
-->
<select id="queryUser" parameterType="map" resultType="user">
select * from usr
<where>
<choose>
<when test="id != null" >
id =#{id}
</when>
<when test="username != null" >
and username = #{username}
</when>
<otherwise>
and id= 4
</otherwise>
</choose>
</where>
</select>
  • set 标签语句示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--
这里set元素会动态前置set关键字,同时也会删除掉无关的逗号
因为用了条件语句之后很可能就会生成的sql后面留下这些逗号,通常与if标签一起使用
-->
<update id="updateUsr" parameterType="map">
update usr
<set>
<if test="username !=null">
username =#{username}
</if>
</set>
where id = #{id}
</update>
  • foreach 标签语句示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!--
collection 表示迭代集合的名称,可以使用@Param注解指定,如下图所示 该参数为必选
item 表示本次迭代获取的元素,若collection为List、Set或者数组,则表示其中的元素;
若collection为map,则代表key-value的value,该参数为必选
open 表示该语句以什么开始,最常用的是左括弧’(’,注意:mybatis会将该字符拼接到整体的sql语句之前,并且只拼接一次,该参数为可选项
close 表示该语句以什么结束,最常用的是右括弧’)’,注意:mybatis会将该字符拼接到整体的sql语句之后,该参数为可选项
separator mybatis会在每次迭代后给sql语句append上separator属性指定的字符,该参数为可选项
index 在list、Set和数组中,index表示当前迭代的位置,在map中,index代指是元素的key,该参数是可选项。
-->

<!--
第一步:迭代集合,获取对应的item,和外部的(),拼接形成('zhangsan')
第二步:在之前的基础上拼接上逗号分隔符('zhangsan'),
第三步:继续迭代并拼接逗号 ('zhangsan'),('lisi'),
第四步:继续迭代并拼接逗号 ('zhangsan'),('lisi'),('wangwu')
-->
<foreach collection="list" item="item" separator=",">
(#{item})
</foreach>


<!--
第一步:拼接open指定的开始字符 (
第二步:迭代集合,拼接对应的item, ('zhangsan'
第三步:拼接separator指定的分隔符 ('zhangsan',
第四步:迭代集合,拼接对应的item, ('zhangsan','lisi'
第五步:拼接separator指定的分隔符('zhangsan','lisi',
第六步:拼接close指定的闭合字符 ('zhangsan','lisi','wangwu')
-->
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item}
</foreach>

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 这是dao/mapper中的方法   
List<MyFile> selectById(@Param("abc") List<String> list);-->

  <select id="selectById" resultMap="BaseResultMap" parameterType="String">
SELECT *
FROM file
 where id in
   <foreach collection="abc" item="item" index="index" separator="," open="(" close =")">
#{item}
</foreach>

</select>
  • 拓展<sql>标签
1
2
3
4
5
6
7
8
9
-含义

定义常量及作用于引用

-场景

当多种类型的查询语句的查询字段或者查询条件形同时,可以将其定义为常量,方便调用。

为求<select>标签结构清晰,也可将sql语句分解

例子

1
2
3
4
<!-- 查询字段 -->
<sql id="Base_Column_List">
ID,MAJOR,BIRTHDAY,AGE,NAME,HOBBY
</sql>
1
2
3
4
5
6
	<!-- 查询所有,不分页 -->
<select id="selectAll" resultMap="BaseResultMap">
SELECT
<include refid="Base_Column_List" />
FROM student
</select>
  • PageHelper分页插件

导入坐标

1
2
3
4
5
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.4</version>
</dependency>

mybatis-config.xml中配置拦截器插件

1
2
3
4
5
<plugins>		
<plugin interceptor="com.github.pagehelper.PageHelper">
<property name="dialect" value="mysql"/>
</plugin>
</plugins>

***ps:***5.x后为PageHelperInterceptor,之前为PageHelper

1
2
3
4
5
6
7
<plugins>
<!--5.x使用PageInterceptor-->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>

使用方法

1
2
PageHelper.startPage(pageNum,pageSize);
PageInfo<User> page=new PageInfo<>(结果集);

***ps:***只有紧跟在PageHelper.startPage方法后的第一个Mybatis的查询(Select)方法会被分页

  • 可调用的API
    • getTotal():获取总数量
    • getList().size():当前查询记录
    • getPageNum():获取当前页码
    • getPageSize():每页显示数量
    • getPages:总页数

1.1.3逆向工程

MyBatis Generator(简称MBG),如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的po类,xxxMapper.xml,xxxMapper.java文件,这显然需要花费巨大的精力,而且可能由于表字段太多,写错了而不知道也是可能的。

插件使用流程如下:

  1. 添加maven依赖
1
2
3
4
5
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
  1. 新增generatorConfig.xml文件

​ a.连接数据库的配置,包括数据名称,数据库用户名密码等配置

​ b.指定要生成代码的包名,包括实体类po的包名,mapper的包名等

​ c.指定数据库中哪些表需要生成文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?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>
<!-- <properties resource="mybatis.properties" />-->
<context id="msqlTables" targetRuntime="MyBatis3">
<!-- 生成的Java文件的编码 -->
<property name="javaFileEncoding" value="UTF-8"/>
<!-- 格式化java代码 -->
<property name="javaFormatter" value="org.mybatis.generator.api.dom.DefaultJavaFormatter"/>
<!-- 格式化XML代码 -->
<property name="xmlFormatter" value="org.mybatis.generator.api.dom.DefaultXmlFormatter"/>

<plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>

<!-- 一定要这枚配置命名规则,否则 EnumSupportPlugin会有问题 -->
<plugin type="org.mybatis.generator.plugins.RenameExampleClassPlugin">
<property name="searchString" value="Example$"/>
<property name="replaceString" value="Criteria"/>
</plugin>

<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
<property name="suppressDate" value="true"/>
</commentGenerator>

<jdbcConnection connectionURL="jdbc:mysql://localhost:3306/db1?useUnicode=true&amp;characterEncoding=UTF-8&amp;autoReconnect=true"
driverClass="com.mysql.jdbc.Driver" password="root" userId="root" >
<property name="nullCatalogMeansCurrent" value="true"/>
<!--设置可以获取tables remarks信息-->
<property name="useInformationSchema" value="true"/>
<!--设置可以获取remarks信息-->
<property name="remarks" value="true"/>
</jdbcConnection>

<!--java类型处理器 用于处理DB中的类型到Java中的类型,默认使用JavaTypeResolverDefaultImpl-->
<javaTypeResolver type="org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl">
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL和NUMERIC类型解析为java.math.BigDecimal -->
<property name="forceBigDecimals" value="true" />
</javaTypeResolver>

<!--
targetPackage:生成的类要放的包,真实的包受enableSubPackages属性控制;
targetProject:目标项目,指定一个存在的目录下,生成的内容会放到指定目录中,如果目录不存在,MBG不会自动建目录
-->
<javaModelGenerator targetPackage="com.unfair.db.model" targetProject="src/main/java">
<!-- for MyBatis3/MyBatis3Simple 自动为每一个生成的类创建一个构造方法,构造方法包含了所有的field;而不是使用setter; -->
<property name="constructorBased" value="false"/>
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>

<!-- targetProject:mapper映射文件生成的位置,重要!! -->
<sqlMapGenerator targetPackage="com.unfair.db.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>

<!-- targetPackage:mapper接口生成的位置,重要!! -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.unfair.db.dao" targetProject="src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>

<!-- 指定数据库表,要生成哪些表,就写哪些表,要和数据库中对应,不能写错! -->
<table tableName="usr" domainObjectName="User"
enableCountByExample="true"
enableUpdateByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
selectByExampleQueryId="true" >
<!--
useActualColumnNames用于指定生成实体类时是否使用实际的列名作为实体类的属性名。取值true或false:
true : MyBatis Generator会使用数据库中实际的字段名字作为生成的实体类的属性名。
false : 这是默认值。如果设置为false,则MyBatis Generator会将数据库中实际的字段名字转换为Camel Case风格作为生成的实体类的属性名。
如果明确的使用columnOverride元素指定了字段对应的实体的属性名,那么useActualColumnNames会被忽略。
-->
<property name="useActualColumnNames" value="false"/>
</table>
</context>
</generatorConfiguration>
  1. 修改好文件后,有两种方式

    • java代码方式

    注意点

    使用逆向工程时,最好新建一个工程,如果你在原来的工程中使用,那也可以,
    
    但是有一定的风险,因为mybatis是根据配置文件中配置的路径来生成的文件的,
    
    如果你工程中有相同名字的文件,那么就会被新生成的文件所覆盖。所以实际开发中,
    
    我们一般新建一个工程,将生成的文件复制到自己的所需的工程中。	
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    package com.truly.test;

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

    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;

    public class GeneratorTest {
    public void testGenerator() throws Exception {
    List<String> warnings = new ArrayList<>();
    boolean overwrite = true;
    //指定逆向工程配置文件
    File configFile = new File(GeneratorTest.class.getResource("/generatorConfig.xml").getFile());
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callback = new DefaultShellCallback(overwrite);
    MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,callback,warnings);
    myBatisGenerator.generate(null);
    }

    public static void main(String[] args) throws Exception {
    GeneratorTest generator = new GeneratorTest();
    generator.testGenerator();
    }
    }

    • 安装插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<build>
<plugins>
<!-- 自动生成mybatis配置文件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>1.7.25</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>

点击菜单run中Configurations(图)

点击加号,并选择maven(图)

在name和Commond line分别填上如上图所示,apply和ok(图)

点击如下运行(图)

生成示例(图)	

1.1.4 mybatis缓存

须知

缓存

    1.存在内存中的临时数据

    2.将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)

      查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题

优点

    减少和数据库的交互次数,减少系统开销,提高系统效率

使用前提

    经常查询并且不经常改变的数据		

mybatis缓存

mybatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。

mybatis系统中默认定义了两级缓存:一级缓存和二级缓存。

  • 默认情况下,只有一级缓存开启(sqlSession级别的缓存,也称为本地缓存)

  • 二级缓存需要手动开启和配置,它是基于namespace级别的缓存。

为了提高扩展性,Mybatis定义了缓存接口Cache。操作者可以通过实现Cache接口来自定义二级缓存

一级缓存

  • 含义
    • 一级缓存也叫本地缓存(session级别的缓存)
      • 与数据库同一次会话期间查询到的数据会放在本地缓存中
      • 以后如果需要获取相同的数据,直接从换缓存中拿,没必须再去查询数据库

二级缓存

  • 含义
    • 二级缓存是基于基于namespace级别的缓存
      • 多个Sqlsession去操作同一个mapper的sql时,不论Sqlsession是否相同,只要namespace相同就能共享数据。

文章作者: truly
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 truly !
 上一篇
JAVA-012-初识spring JAVA-012-初识spring
Spring是轻量级的ioc(控制反转)和aop(面向切面)容器框架。通过控制反转的技术达到松耦合的目的,提供面向切面编程的丰富支持....
2022-01-17
下一篇 
JAVA-010-初识MySQL JAVA-010-初识MySQL
MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一!
2022-01-15
  目录