从头学Mybatis

一.mybatis基本组件:

1.mybatis特点:

1).支持自定义sql,存储过程,高级映射

2).实现自动对sql进行参数设置,并且能自动对结果集进行解析和封装

3).通过注解或者xml进行映射,大大减少代码量

4).数据源信息通过 配置文件进行配置

2.基本组件:

组件示意图

2.1 配置文件:

全局配置文件mybatis-config.xml 作用:配置数据源,引入资源文件,配置不同环境,以及引入其他映射文件等等。
mybatis-config.xml讲究严格的顺序,具体顺序遵循文档的顺序
配置顺序

2.1.1 properties属性 读取外部资源文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis
username=root
password=root
<!-- 引入外部资源文件,resource:相对路径,url:绝对路径 -->
	<properties resource="jdbc.properties" />

通过properties引入外部文件之后,就可以通过${xxx}读取文件了

2.1.2 setting属性配置:

setting
驼峰匹配:经典的数据库命名到经典的java中命名,就相当于去掉数据库中名字的下斜杠"_",与java匹配及第二个单词首字母大写
问题:在mybatis-config.xml写sal的时候,发现java对象与数据库列名不一样怎么解决?
1.开启驼峰命名自动匹配 如数据库 user_name java:userName .
2.使用别名替代

<settings>
		<!-- 开启驼峰匹配:经典的数据库列名(多个单词下划线连接)映射到经典的java属性名(多个单词驼峰连接) -->
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>
2.1.3 typeAliases

类型别名是为Java类型命名一个比较短的名字。它之和xml配置有关,存在的意义仅限于用来减少类完全限定名的冗余。
有两种方式可供选择:

<typeAliases>
		<!-- 类型别名:type-pojo类的全路径,alias-别名名称(可随便写,推荐和类名一致) -->
		<!-- <typeAlias type="cn.itcast.mybatis.pojo.User" alias="user" /> -->
		<!-- 开启别名包扫描,name:包路径,扫描的别名就是类名,并且大小写不敏感 -->
		<package name="cn.itcast.mybatis.pojo"/>
	</typeAliases>
<?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>
	<!-- 引入外部资源文件,resource:classpath路径,url:绝对路径(不建议使用) -->
	<properties resource="jdbc.properties"></properties>
	<settings>
		<!-- 开启驼峰匹配:经典的数据库列名(多个单词下划线连接)映射到经典的java属性名(多个单词驼峰连接) -->
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>
	**<typeAliases>
		<!-- 类型别名:type-pojo类的全路径,alias-别名名称(可随便写,推荐和类名一致) -->
		<typeAlias type="cn.study.mybatis.pojo.User" alias="user" />
	</typeAliases>**
	<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="UserMapper.xml" />
		<mapper resource="UserDaoMapper.xml" />
	</mappers>
</configuration>
2.1.4 typeHandlers(类型处理器)

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时,都会用类型处理器将获取的值以合适的方式转换成 Java 类型。下表描述了一些默认的类型处理器。

2.1.5 plugins (插件又称拦截器)

拦截器动态修改sql
拦截器分页原理与使用

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)
    在这里插入图片描述
    在这里插入图片描述
2.1.6 environments(环境)

MyBatis 可以配置成适应多种环境,例如,开发、测试和生产环境需要有不同的配置;
尽管可以配置多个环境,每个 SqlSessionFactory 实例只能选择其一。
虽然,这种方式也可以做到很方便的分离多个环境,但是实际使用场景下,我们更多的是选择使用spring来管理数据源,来做到环境的分离。

添加一个test(测试)环境,并在default参数中指向test环境。
在这里插入图片描述
通过build方法的重载方法
在这里插入图片描述
在这里插入图片描述

2.1.7 Mappers

既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要定义 SQL 映射语句了。但是首先我们需要告诉 MyBatis 到哪里去找到这些语句。Java 在自动查找这方面没有提供一个很好的方法,所以最佳的方式是告诉 MyBatis 到哪里去找映射文件。
1.方式一:
在mybatis-config.xml引入项目目录下的映射文件:
2.方式二:
在mybatis-config.xml配置mapper接口的全路径:
这种配置方式,在全局配置文件中配置了mapper接口的全路径,并没有配置mapper接口的映射文件的位置。如果要让mybatis找到对应的映射文件,则必须满足一定的条件或规则:
1、映射文件和mapper接口在同一个目录下
2、文件名必须一致
3.映射文件的namespace必须和mapper接口的全路径保持一致

<mappers>
		<!-- <mapper resource="UserMapper.xml"/> -->
		<mapper resource="UserDaoMapper.xml"/>		
		<mapper class="cn.study.mapper.UserMapper"/>
</mappers>

总结:
1.properties:引入外部资源文件 jdbc.properties resource:classpath路径 url:物理路径
2.settings:行为参数,mapUnderscoreToCamelCase:驼峰匹配,从经典的数据库列名到经典的java属性名的映射
3.typeAliases:类型别名, typeAlias(type:包装类的全路径,alias:别名名称) package(name:包的全路径)
4.typeHandlers:类型处理器(预处理语句接收参数时,抽取结果集时)
5.plugins:插件又称拦截器
6.environments:环境,default:指定采用那个环境 配置多个环境(id:唯一标识, transactionManager:事务管理器,type=JDBC;dataSource:数据源)
7.mappers:引入映射文件,mapper(resource:classpath路径 url:物理路径 class:mapper接口的路径(同包同名,namespace是接口的全路径)),package(name:mapper接口包的全路径)

2.2 Mapper 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="cn.study.mapper.UserMapper">
	<select id="queryUserById" resultType="cn.itcast.pojo.User">
		select * from tb_user where id = #{id}
	</select>
	
	<select id="queryUserAll" resultType="user">
		select * from tb_user
	</select>
	
	<insert id="insertUser" parameterType="cn.itcast.pojo.User">
		INSERT INTO tb_user (
			user_name,
			password,
			name,
			age,
			sex,
			birthday,
			created,
			updated
		)
		VALUES
			(
				#{userName},
				#{password},
				#{name},
				#{age},
				#{sex},
				#{birthday},
				NOW(),
				NOW()
			);
	</insert>
	
	<update id="updateUser" parameterType="cn.itcast.pojo.User">
		UPDATE tb_user
		SET
		 user_name = #{userName},
		 password = #{password},
		 name = #{name},
		 age = #{age},
		 sex = #{sex},
		 birthday = #{birthday},
		 updated = NOW()
		WHERE
			(id = #{id});
	</update>
	
	<delete id="deleteUserById" parameterType="java.lang.Long">
		delete from tb_user where id=#{id}
	</delete>
</mapper>

2.2.1 parameterType传入参数

CRUD标签都有一个属性parameterType,statement通过它指定接收的参数类型。
接收参数的方式有两种:
1、#{}预编译
2、${}非预编译(直接的sql拼接,不能防止sql注入)
参数类型有三种:
1、基本数据类型
2、HashMap(使用方式和pojo类似)
3、Pojo自定义包装类型

1.$ {}用法:
场景:数据库有两个一模一样的表。历史表,当前表
查询表中的信息,有时候从历史表中去查询数据,有时候需要去新的表去查询数据。希望使用1个方法来完成操作。
注意:
使用$ {} 去接收参数信息,在一个参数时,默认情况下必须使用${value}获取参数值,
而#{} 只是表示占位,与参数的名字无关,如果只有一个参数,可以使用任意参数名接收参数值,会自动对应,一般会在mapper类的方法参数里面,给参数添加@Param主注解。

2.多个参数
当mapper接口要传递多个参数时,有两种传递参数的方法:
1、 默认规则获取参数{0,1,param1,param2}
2、 使用@Param注解指定参数名

3 HashMap

  1. 基本数据类型
  2. hashMap
  3. pojo包装类
    前面已经使用了基本数据类型和pojo类型的参数,那么hashMap这种类型的参数怎么传递参数呢?
    其实,它的使用方式和pojo有点类似,简单类型通过#{key}或者 k e y , 复 杂 类 型 通 过 {key},复杂类型通过 key{key.属性名}或者#{key.属性名}

2.2.2 ${}与#{}区别

在这里插入图片描述
#{}:预编译 编译成占位符 可以防止sql注入 不需要关注数据类型 一个参数时,默认任意参数名可以接收参数
${}:非预编译 直接的sql拼接 不可以防止sql注入 需要关注数据类型 一个参数时,默认必须是value接收参数

2.2.3 模糊查询:

1.表达式: name like"%"#{name}"%"

==> Preparing: select * from bbs_brand WHERE namelike"%"?"%"and falg=? limit 0 , 10

==>Parameters: 莲(String), 1(Integer)
这个最后生成的sql 为 where name like “%” ‘莲’ “%” 能查出来;

2.表达式: name like '%${name}%'

Preparing:select count(0) from (select * from bbs_brand WHERE name like’%莲%’ and falg=?) as total

Parameters: 1(Integer)
使用$ 进行字符串的拼接,直接将值拼接上去.

3.表达式:name like CONCAT(’%’,’${name}’,’%’)**

==> Preparing: select count(0) from (select *from bbs_brand WHERE name likeCONCAT(’%’,‘莲’,’%’) and falg=?) astotal

4.update bbs_brand set is_display=0 where id IN (${ids})**
这里只能用 ${} ,当我们传入的字符串是1,3,5,7的时候,用#只能删除id为1的品牌,其他的就不能删除了,这是因为,使用了#,就是一个占位符了,经过编译后是
where id in(?) 加入字符串后是 where id in(‘1,3,5,7’) 这种,在SQL中就只会删除一个。正确的应该是where id in(‘1’,‘3’,‘5’);

2.2.4 resultMap

在这里插入图片描述

  1. 解决列名与属性名不一致的问题:
    查询数据的时候,查不到userName的信息,原因:数据库的字段名是user_name,而POJO中的属性名字是userName
    两端不一致,造成mybatis无法填充对应的字段信息。修改方法:在sql语句中使用别名
    解决方案1:在sql语句中使用别名
    解决方案2:参考驼峰匹配 — mybatis-config.xml 的时候
    解决方案3:resultMap自定义映射

UserMapper.xml中配置resultMap
在这里插入图片描述
在UserMapper.xml中使用resultMap:
在这里插入图片描述
2.resultMap的自动映射:
在上面讲的resultMap中,主键需要id标签设置,这杨可以提高性能,然后通过result标签配置表列名和属性名对应起来,那么问题来了,是不管列名与属性对不对应都要配置还是只用配置不对应的列名?
这个取决于resultMap中的 autoMapping属性的值:
如果为true:resultMap中没有配置的字段会自动对应.
如果为false:只会针对result中已经配置的字段进行映射。
并且resultMap会自动映射单表查询的结果集。
这里千万要注意,这里配置的是resultMap 而不是 resultType 如果写错了会报错 说找不到userMap这个类!!

2.3 动态sql

<select id="queryUserListLikeUserName" resultType="User">
		select * from tb_user where sex &lt; 2
		<!-- if:判断
			test:OGNL表达式或者简单的java代码
		 -->
		<if test="userName!=null &amp;&amp; !''.equals(userName)">
			 and user_name like '%' #{userName} '%'
		</if>
	</select>
	
	<select id="queryUserListLikeUserNameOrAge" resultType="User">
		select * from tb_user where sex=1 
		<!-- choose:条件选择
			when:test-条件,使用方式参考if的test属性,一旦有一个成立,后续的when都不再执行
			otherwise:所有的when都不成立时,才会执行
		 -->
		<choose>
			<when test="userName!=null and userName.trim()!=''">and user_name like '%' #{userName} '%'</when>
			<when test="age != null">and age = #{age}</when>
			<otherwise>and user_name = 'zhangsan' </otherwise>
		</choose>
	</select>
	
	<select id="queryUserListLikeUserNameAndAge" resultType="User">
		select * from tb_user
		<!-- 
			自动添加where关键字
			有一定的纠错功能:去掉sql语句块之前多余的一个and|or
			通常结合if或者choose使用
		 -->
		<where>
			<if test="userName!=null and userName.trim()!=''">user_name like '%' #{userName} '%'</if>
			<if test="age!=null">and age = #{age}</if>
		</where>
	</select>
	
	<update id="updateUserSelective" >
		UPDATE tb_user
		<!-- 
			set自动添加set关键字
			也有一定的纠错功能:自动去掉sql语句块之后多余的一个逗号
		 -->
		<set>
		 <if test="userName!=null and userName.trim()!=''">user_name = #{userName},</if>
		 <if test="password!=null and password.trim()!=''">password = #{password},</if>
		 <if test="name!=null and name.trim()!=''">name = #{name},</if>
		 <if test="age!=null">age = #{age},</if>
		 <if test="sex!=null">sex = #{sex}</if>
		</set>
		WHERE
			(id = #{id});
	</update>
	
	<select id="queryUserListByIds" resultType="User">
		select * from tb_user where id in 
		<!-- 
			foreach:遍历集合
			collection:接收的集合参数
			item:遍历的集合中的一个元素
			separator:分隔符
			open:以什么开始
			close:以什么结束
		 -->
		<foreach collection="ids" item="id" separator="," open="(" close=")">
			#{id}
		</foreach>
	</select>

二. mysql缓存:

执行相同的sql和参数,mybatis不执行sql,而是直接从缓存中命中返回。

1.一级缓存:

在mybatis中,一级缓存是默认开启的,并且一直无法关闭,在同一个sqlSession下。
使用:sqlSession.clearCache();可以强制清除缓存

执行update、insert、delete的时候,会清空缓存

2.二级缓存:

mybatis 的二级缓存的作用域:
1、同一个mapper的namespace,同一个namespace中查询sql可以从缓存中命中。
2、跨sqlSession,不同的SqlSession可以从二级缓存中命中
怎么开启二级缓存:
1、在映射文件中,添加标签
2、在全局配置文件中,设置cacheEnabled参数,默认已开启。
注意:
由于缓存数据是在sqlSession调用close方法时,放入二级缓存的,所以第一个sqlSession必须先关闭
二级缓存的对象必须序列化,例如:User对象必须实现Serializable接口。

开启二级缓存,在映射文件(UserMapper.xml)中添加:
这里的sql只会执行第一次。

@Test
	public void testCache2(){
		User user1 = this.userMapper.queryUserById(1l);
		System.out.println(user1);
		// 注意:关闭sqlSession
		sqlSession.close();
		System.out.println("=================第二次查询======================");
		// 重新打开一个sqlSession会话
		SqlSession sqlSession2 = this.sqlSessionFactory.openSession();
		// 通过sqlSession2重新实例化UserMapper
		this.userMapper = sqlSession2.getMapper(UserMapper.class);
		User user2 = this.userMapper.queryUserById(1l);
		System.out.println(user2);
	}

关闭二级缓存:
不开启,或者在全局的mybatis-config.xml 中去关闭二级缓存
在这里插入图片描述
在mybatis-config.xml配置中:

<settings>
		<!-- 行为参数,name:参数名,value:参数值,默认为false,true:开启驼峰匹配,即从经典的数据库列名到经典的java属性名 -->
		<setting name="mapUnderscoreToCamelCase" value="true"/>
		<!-- 关闭二级缓存,默认是开启,false:关闭 -->
		<setting name="cacheEnabled" value="false"/>
	</settings>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值