简介
(1) 持久层框架比较
hibernate:全表映射,效率高,多表联合查询支持差。不支持存储过程,不能优化SQL。
mybatis:半自动映射,手动匹配映射关系,手动编写SQL,工作量大。可动态SQL,优化SQL。
(2) 下载jar包方式
官网:https://github.com/mybatis
解压 jar 将 mybatis.jar加入项目lib中
(3) maven依赖方式
查询网址:https://mvnrepository.com
1. 核心配置
根标签:<configuration>
Spring整合项目不需要配置Mybatis核心配置
属性按属性配置:properties>settings>typeAliases>typeHandlers>objectFactory>objectWrapperFactory>reflectFactory>plugins>environments>databaseIdProvider>mappers
文件夹【src】或【java/main/resources】下新建mybatis-config.xml(内容可从官方API复制)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
1.1 <properties> 属性
1.1.1 外部引用
文件夹【src】或【java/main/resources】下新建【db.properties】或【jdbc.properties】文件
1.1.2 内部属性
1.1.3 内外属性共用
<!-- 属性 -->
<properties resource="org/mybatis/mybatis-config.properties" >
<property name="username" value="root"/>
<property name="password" value="root"/>
</properties>
1.2 <settings> 设置
用来改变Mybatis运行行为,开启二级缓存,开启延时加载等。
(1) 二级缓存:<setting name="cacheEnabled" value="false" />// true(开启), false(默认关闭)
(2) 延时加载:<setting name="lazyLoadingEnabled" value="false" /> // true(开启), false(默认关闭)
<!-- 设置 -->
<settings>
<!-- 二级缓存 true:开启,false(default):关闭-->
<setting name="cacheEnabled" value="false" />
<!-- 延迟加载 true:开启,false(default):关闭(立即加载)-->
<setting name="lazyLoadingEnabled" value="false" />
<!-- 只有lazyLoadingEnabled为true才生效-->
<!-- 按需加载 true:开启(默认,任意访问加载),false:关闭(深度延迟)-->
<setting name="aggressiveLazyLoading" value="true" />
<!-- 是否允许单一语句返回多结果集 true(default):允许,false:不允许-->
<setting name="multipleResultSetsEnabled" value="true" />
<!-- 使用列标签代替列名 true(default):允许,false:不允许-->
<setting name="useColumnLabel" value="true"/>
<!-- JDBC自动生成主键 true:允许,false(default):不允许-->
<setting name="useGeneratedKeys" value="false"/>
<!-- 自动映射列名属性 NONE:取消自动,PARTIAL(default):只映射没有嵌套结果集的映射,FULL:自动映射任意结果集-->
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<!-- 默认执行器 SIMPLE(default):普通,REUSE:预处理,BATCH:批处理-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- 超时时间(等待数据库响应秒数,随驱动默认)-->
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="safeResultHandlerEnabled" value="true"/>
<!-- 自动驼峰命名规则 true:允许,false(default):不允许-->
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<!-- 为null指定JDBC类型 NULL,VARCHAR,OTHER(default)-->
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value=""/>
<setting name="defaultScriptingLanguage" value=""/>
<setting name="returnInstanceForEmptyRow" value=""/>
<setting name="logPrefix" value=""/>
<setting name="logImpl" value=""/>
<setting name="vfsImpl" value=""/>
<setting name="useActualParamName" value=""/>
<setting name="configurationFactory" value=""/>
</settings>
1.3 <typeAliases> 类型命名
映射文件查询的返回值匹配的类型别名
1.3.1 自定义别名
(1) 默认配置:
核心配置:无
映射配置:<select id="xx" resultType="包名.类名"/>
(2) 指定别名:
核心配置:<typeAlias alias="别名" type="包名.类名" />
映射配置:<select id="xx" resultType="别名"/>
(3) 类名别名:
核心配置:<typeAlias type="包名.类名" />
映射配置:<select id="xx" resultType="不区分大小写类名"/>
(4) 全包命名:
核心配置:<package name="包名.包名" />
映射配置:<select id="xx" resultType="不区分大小写类名"/>
注释:(3)(4)更改别名,实体类类注解@Alias(value="别名") // @alias("别名")
<!-- 类型别名 -->
<typeAliases>
<!-- 方式1:单个类别名指定-->
<typeAlias alias="user" type="com.entity.User"/>
<!-- 方式2:省略alias,默认类名,Bean加@Alias(value="user")注解 改别名 -->
<typeAlias type="com.entity.User"/>
<!-- 方式3:自动扫描包,默认类名,Bean加@Alias(value="user")注解 改别名 -->
<package name="com.entity"/>
</typeAliases>
1.3.2 内置别名
注释:alias属性映射文件中使用时不区分大小写(type为对应接口函数的返回值类型)
<typeAliases>
<!-- 基本类型,别名前加_, alias为别名, type为java类型-->
<typeAlias alias="_byte" type="byte"/>
<typeAlias alias="_short" type="short"/>
<typeAlias alias="_int" type="int"/>
<typeAlias alias="_integer" type="int"/>
<typeAlias alias="_long" type="long"/>
<typeAlias alias="_float" type="float"/>
<typeAlias alias="_double" type="double"/>
<typeAlias alias="_boolean" type="boolean"/>
<typeAlias alias="_char" type="char"/><!-- 3.5.10-->
<typeAlias alias="_character" type="char"/><!-- 3.5.10-->
<!-- 引用类型-->
<typeAlias alias="byte" type="Byte"/>
<typeAlias alias="short" type="Short"/>
<typeAlias alias="int" type="Integer"/>
<typeAlias alias="integer" type="Integer"/>
<typeAlias alias="long" type="Long"/>
<typeAlias alias="float" type="Float"/>
<typeAlias alias="double" type="Double"/>
<typeAlias alias="boolean" type="Boolean"/>
<typeAlias alias="char" type="Char"/><!-- 3.5.10-->
<typeAlias alias="character" type="Char"/><!-- 3.5.10-->
<typeAlias alias="string" type="String"/>
<typeAlias alias="date" type="Date"/>
<typeAlias alias="decimal" type="BigDecimal"/>
<typeAlias alias="bigDecimal" type="BigDecimal"/>
<typeAlias alias="bigInteger" type="BigInteger"/>
<typeAlias alias="object" type="Object"/>
<typeAlias alias="date[]" type="Date[]"/>
<typeAlias alias="decimal[]" type="BigDecimal[]"/>
<typeAlias alias="bigDecimal[]" type="BigDecimal[]"/>
<typeAlias alias="bigInteger[]" type="BigInteger[]"/>
<typeAlias alias="object[]" type="Object[]"/>
<typeAlias alias="map" type="Map"/>
<typeAlias alias="hashMap" type="HashMap"/>
<typeAlias alias="list" type="List"/>
<typeAlias alias="arrayList" type="ArrayList"/>
<typeAlias alias="collection" type="Collection"/>
<typeAlias alias="iterator" type="Iterator"/>
</typeAliases>
1.4 <typeHandlers> 类型处理器
java类型与jdbc类型转换,映射文件不用指定参数类型,默认自动映射。
1.5 <objectFactory> 对象工厂
1.6 <plugins> 插件
1.7 <environments> 数据库连接环境
(1) 数据库连接环境配置:<environments default="默认id">
(2) 数据库连接环境:<environment id="xx">
(3) 事务管理器:<transactionManager type="JDBC"/> //JDBC手动提交事务,MANAGED被管理
(4) 数据源:<dataSource type="POOLED"> //POOLED连接池,UNPOOLED每次打开关闭,JNDI其它。
(5) 参数:<property name="driver|url|username|password" value="${xx}" />
<!--配置多个连接数据库的环境-->
<environments default="development"><!-- default:默认连接环境-->
<!-- 单个数据库连接环境 -->
<environment id="development"><!-- id:唯一标识 -->
<!-- 事务管理器 -->
<!-- type: JDBC 执行SQL 使用JDBC原生事务管理,手动提交回滚 -->
<!-- type: MANAGED 被管理 -->
<transactionManager type="JDBC"/>
<!-- 配置数据库信息 -->
<!-- type: POOLED 使用数据库连接池,缓存数据连接 -->
<!-- type: UNPOOLED 每次请求打开关闭连接 -->
<!-- type: JNDI 使用其他管理的数据源 -->
<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>
1.8 <databaseIdProvider> 数据库厂商表示
1.9 <mappers> 映射器
1.9.1 核心配置映射器
<!--引入映射文件-->
<mappers>
<!-- 方式1: 类路径-->
<mapper resource="com/mappers/UserMapper.xml"/>
<!-- 方式2: 本地文件路径, 盘符后正反斜线效果相同-->
<mapper url="file:///D:\com\mappers\UserMapper.xml"/>
<!-- 方式3: 接口类(注解方式)-->
<mapper class="com.mappers.UserMapper"/>
<!-- 方式4: 全包扫描-->
<package name="com.mappers"/>
</mappers>
1.9.2 映射文件
(1) 命名空间:<mapper namespace="包.类">...</mapper>
注释:特殊符号用<![CDATA[ > ]]> 包裹,也可写文本 <![CDATA[ where a > 1 and ... ]]>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mappers.UserMapper">
<select id="selectUser" resultType="user">
select * from user
</select>
</mapper>
2. 工厂类
2.1 配置文件
加载: InputStream in = Resource.getResourceAsStream("mybatis-config.xml");
2.2 工厂类
获取:SqlSessionFactory ssf = new SqlSessionFactoryBuiler().build(in);
注释:sqlsessionFactory线程安全整个应用执行期间都存在创建多个会使得数据库资源耗尽。
2.3 会话
2.3.1 手动提交
(1) 获取会话:SqlSession ss = ssf.openSession();
(2) 手动提交: ss.commit();
2.3.2 自动提交
(1) 获取会话:SqlSession ss = ssf.openSession(true);
注释:SQL执行后自动提交
2.3.3 关闭会话
(1) 关闭会话:ss.close();
2.4 接口
(1) 获取接口对象:XxMapper mapper = ss.getMapper(XxMapper.class);
(2) 指定映射文件:int result = ss.insert | selectList("con.xx.UserMapper.adduser", User);
2.5 缓存
2.5.1 一级缓存
1级缓存是SqlSession 会话级别,默认开启,不同sqlSession的一级缓存不共享。
(1) 一级缓存失效:1.sqlSession不同,2.查询条件不同,3.执行了增删改SQL,4.手动清空(sqlSession.clearCache())
2.5.2 二级缓存
2级缓存时SqlSessionFactory级别,默认关闭,缓存数据在sqlSession关闭后后生效。
(1) 开启2级缓存:核心配置settings <setting name="cacheEnabled" value="true" />
(2) 映射文件配置:添加 <cache eviction="LRU" flushInterval="30000" size ="512" readOnly="true" />
注释:eviction(缓存回收策略):LRU(最长时间不使用),FIFL(先进先出)
注释:flushinterval 刷新间隔毫秒,默认无间隔
注释:size 缓存对象个数(正整数)
注释:readonly : true(只读缓存,未调用者返回相同实例,不能修改) false(读写缓存,默认)
(3) 实体类:实现序列号接口(implements Serializable)
注释:优先查2级缓存
3. 参数
3.1 获取参数方式
(1) ${参数} //相当于字符串拼接,有SQL注入问题,转换后值没有引号。
必须使用场景: 1批量删除(传"1,2,3",接 in(${参数}=1,2,3)), 2 动态表名( select * from ${参数})
(2) #{参数} // 相当于jdbc的预编译,可防止SQL注入问,转换后的值有引号。
必须使用场景:模糊查询( like '%${参}%')不安全,替代方式1( like concat('%', #{xx}, '%')), 替代方式2( like "%"#{xx}"%")
3.2 传参与接参
3.2.1 单字面量
可指定任意名称获取参数值。
3.2.2 多字面量
方式1:#{arg0}, #{arg1},...
方式2:#{param1}, #{param2},...
3.2.3 map
通过map的key获取参数
3.2.4 实体类
通过实体类的属性获取
3.2.5 注解
注解指定别名
3.3 参数类型 parameterType(增删改查通用)
注释:可选属性 mybatis通过Typehandler推断 可自动设置
3.4 参数映射 parameterMap(查询专有)
注释:不推荐使用的,旧的参数映射方式
4. 结果集
4.1 字面量结果
注释:取得多条结果用List<String>接收返回值
4.2 map结果
* 需要保存DB字段类型自动转换后一致,否则强转会失败。
(1) 单条数据map
(2) 多条数据 List<map>
(3) 多条数据 Map<map>
注释:添加接口函数的注解(表主键)
4.3 结果类型(resultType)
(1) 字段名相同,自动映射。
注释:不一致也可以通过查询字段别名的方式保持一致
(2) 设置自动驼峰转换。
4.4 结果映射(resultMap)
resultMap主要用来处理 表字段和java属性名不一致的情况。
id:唯一标识
type:指定映射的实体类
4.4.1 普通结果集(result)
column:指定查询出的数据库字段名
property:指定实体类属性名
javaType:可省略
注释:有驼峰转换时,property指定下滑字段,column指定驼峰,也可以正常获取数据,但是必须转换后是相同字段名(user_id与userId可以,user_id与id不可以)
4.4.2 构造器结果集(constructor)
4.4.3 主键结果集(id)
4.4.4 一对一结果映射(association)
(1) 文件内部一对一
(2) 分步查询:文件外部子查询
association的column:主查询字段(用来做子查询条件)
(3) 延迟加载:
默认为关闭状态(立即加载),开启需设置全局setting.lazyLoadingEnabled
根据【aggressiveLazyLoading】的值做处理,true:访问任意属性加载,false访问对应的属性才加载(执行sql)。
个别SQL不开启延迟加载的设定:<association fetchType="lazy(延迟加载) | eager(立即加载) "
4.4.5 一对多结果映射(collection)
(1) 文件内部一对多
(2) 分步查询:文件外部一对多
(3) 延迟加载
参照association
4.4.6 discriminator
略
5. 增删改查
5.1 查询
(1) id:唯一标识
(2) resultType:返回值类型
(3) resultMap:返回值映射
(4) flushCache:执行SQL后清除缓存,默认false
(5) useCache:开启二级缓存,默认true
(6) timeout:超时时间,单位秒,超时抛异常
(7) fetchSize:记录总条数
(8) statementType:JDBC工作模式(STATEMENT, PREPARED默认, CALLABLE)
(9) resultSetType:结果集类型(Forward_only, Scroll_Sensitive, Scroll_insensitive)
5.2 插入
(1) id:唯一标识
(2) flushCache:执行SQL后清除缓存,默认false
(3) timeout:超时时间,单位秒,超时抛异常
(4) statementType:JDBC工作模式(STATEMENT, PREPARED默认, CALLABLE)
(5) keyProperty:插入的返回值赋给(参数)实体类的某个属性(一般是主键),多个属性逗号分割。
(6) keyColumn:设置位置或列名指定返回字段(主键不是第一列时设置)多个主键逗号分割。
(7) useGeneratedKeys:使用jdbc的getGeneratedKyes方法取数据库内部主键,默认false
(8) 获取自增主键(mysql, sqlserver)
(9) 获取自增主键(oracle)
注释:oracle不支持上记(keyProperty, keyColumn, useGeneratedKeys)主键自增
selectKey order:before (先执行selectKey 再执行insert) after (先执行Insert 再执行 selectKey)
<insert id="addUser"
parameterType="entity.User"
keyProperty="id,userName"
keyColumn="2,3"
>
<selectKey keyProperty="id"
resultType="Integer"
order="BEFORE"
statementType="PREPARED"
>
select if(max(id) is null, 1, max(id)) as newId from user
</selectKey>
insert into user(id, username, name)
values (#{id}, #{username}, #{name})
</insert>
5.3 更新
注释:同插入一样
(1) id:唯一标识
(2) flushCache:执行SQL后清除缓存,默认false
(3) timeout:超时时间,单位秒,超时抛异常
(4) statementType:JDBC工作模式(STATEMENT, PREPARED默认, CALLABLE)
(5) keyProperty:插入的返回值赋给(参数)实体类的某个属性(一般是主键),多个属性逗号分割。
(6) keyColumn:设置位置或列名指定返回字段(主键不是第一列时设置)多个主键逗号分割。
(7) useGeneratedKeys:使用jdbc的getGeneratedKyes方法取数据库内部主键,默认false
5.4 删除
(1) id:唯一标识
(2) flushCache:执行SQL后清除缓存,默认false
(3) timeout:超时时间,单位秒,超时抛异常
(4) statementType:JDBC工作模式(STATEMENT, PREPARED默认, CALLABLE)
6. SQL元素
(1) 内部无参SQL
(2) 内部有参SQL
(3) 外部SQL
7. 动态SQL
7.1. if 单条件判断
注释:<if test=" xx == 1"> <if test=" xx == '2' "> 不能同时使用,有类型问题
(1) 条件语法:<if test="表达式"> sql内容 </if>
(2) 判空与非空:参数==null, 参数!=null, 参数=='', 参数 != '' // 单双引号可互换
(3) 逻辑控制:!, and, or
7.2. choose 多条件判断
(1) choose:没有属性
(2) when: test="表达式" // 多个when条件,只处理其中一个
(3) otherwise:没有属性 用于默认情况
7.3. where
注释:自动拼接where 并将第一个条件中and或or去掉,解决where 1=1 后的条件拼and的问题。if条件都不满足则没有where关键字 ,不能去除sql末尾关键字。
7.4. trim
(1) prefix:添加前缀,没有满足条件的if则不添加内容
(2) prefixOverrides:去除首个if条件开头的指定字符,多个字符用|分割
(3) suffix:添加整个语句后缀,没有满足条件的if则不添加内容
(4) suffixOverides:去掉最后一个if条件结尾的指定字符,多个字符用|分割
7.5. set
注释:主要用于更新,拼接set语句,去掉最后的,分割
7.6. foreach
(1) item:每次循环的元素,map的值
(2) index:当前元素(数组,list)的下标, map的键
(3) collection:接口参数名(类型可为Array, List, Map)
(4) open:语句前添加的符号
(5) close:语句后添加的符号
(6) separator:每个元素的间隔符号
list
map
7.7. bind
注释:主要用于模糊查询,${...} 无法防止sql注入。concat只适用于mysql, oracle用|| ,不利于项目移植。
相当于将参数与%重新拼接成新的参数
8. 注解SQL
注释:注解SQL无需配置映射xml,需要改 mybatis-config.xml配置,<mapper class="com.mybatis.xxMapper" /> 或全局配置<package name="com.mappers"/> 注解mapper接口与映射文件mapper接口可以放在同一个包下。
8.1 @Select:
8.2 @Insert:
8.3 @Update:
8.4 @Delete:
8.5 一对一注解查询
映射集合:@Results
映射属性:@Result (column 字段|子查询条件,property 实体类属性)
一对一映射:one=@One(select="包.mapper.方法")
8.6 一对多注解查询
9 其它
9.1 逆向工程
根据数据库生成,实体类,接口,映射文件。
(1) 创建maven项目,
(2) 引入插件
<plugins>
<plugin>
<groupid>org.mybatis.generator</groupid>
<artifactid>mybatis-generator-maven-plugin</artifactid>
<version>1.3.0</version>
<depentencies>
<dependency>
<!-- 核心包 -->
<groupid>org.mybatis.generator</groupid>
<artifactid>mybatis-generator-core</artifactid>
<version>1.3.2</version>
</denpendency>
<dependency>
<!-- 数据库连接池 -->
<groupid>com.mchange</groupid>
<artifactid>c3p0</artifactid>
<version>0.9.2</version>
</denpendency>
<dependency>
<!-- 数据库驱动 -->
...
</denpendency>
</plugin>
</plugins>
(3) 创建逆向工程配置文件(generatorConfig.xml 文件名固定)
注释:enableSubPackages是否根据.生成子包,trimStrings是否自动去空格
<?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>
<!-- MyBatis3Simple:基本crud,MyBatis3:基本crud及条件更新-->
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<!-- 数据库连接信息 -->
<jdbcConnection
driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis"
userId="root"
password="root">
</jdbcConnection>
<!-- javaBean生成策略 -->
<javaModelGenerator targetPackage="com.test.mybatis.bean"
targetProject=".\src\main\java">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- 映射文件生成策略 -->
<sqlMapGenerator targetPackage="com.test.mybatis.mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- 接口生成策略 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.test.mybatis.mapper"
targetProject=".\src\main\java\mapper">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 表配置(tableName *代表所有表)-->
<table tableName="t_user" domainObjectName="User" />
</context>
</generatorConfiguration>
(4) 双击执行插件(重新生成需要先删除旧文件)
(5) 更新条件(Mybatis3)
mapper.selectByExample(null)// 查询所有数据
Example e = new Example();
e.createCriteria()//创建一个条件
.and字段名xx() // and连接条件
.or() //or连接后面条件
.and...
mapper.updateByPrimaryKey(实体类) // null字段正常更新
mapper.updateByPrimaryKeySelective(实体类) //不更新值为null的属性。
9.2 分页插件
(1) 导入依赖(pom.xml)
<dependency>
<groupid>com.github.pagehelper</groupid>
<artifactid>pagehelper</artifactid>
<version>5.2.0</version>
</dependency>
(2) 配置插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
</plugin>
</plugins>
(3) 获取分页数据
PageHelper.startPage(第几页, 一页件数);
mapper.select... //可获取到对应的件数数据
(4) 获取全部数据后分页
PageInfo<实体类> page= new PageInfo(list, 总页数);
// page可获取,总页数,总件数,单页数据数,等待。