MyBatis学习笔记(下)

六、自定义映射resultMap

解决字段名和属性名不一致的情况
方式一
给属性起别名在sql语句中
数据库中的名字
在这里插入图片描述
实体类中的名字
在这里插入图片描述
起别名
在这里插入图片描述
方式二
在config.xml中使用< settings>< /settings> 设置MyBatis的全局配置 ! 注意标签的放的位置

将下划线_自动映射为驼峰命名 emp_name : empName

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

方式三

resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识

type:查询的数据要映射的实体类的类型
子标签:

id:设置主键的映射关系

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

association:设置多对一的映射关系

collection:设置一对多的映射关系
属性:

property:设置映射关系中实体类中的属性名

column:设置映射关系中表中的字段名

<resultMap id="userMap" type="User">
<id property="id" column="id"></id>
<result property="userName" column="user_name"></result>
<result property="password" column="password"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
</resultMap>
<select id="getAllEmp"  resultMap="empResultMap">
  select eid,emp_name empName,password,age,sex,email from  t_emp 
</select>

七、多对一与一对多映射处理

查询员工信息以及员工所对应的部门信息

方法一:级联属性赋值
column是数据库中字段的名字
property 是实体类中的属性
在这里插入图片描述
2.使用association处理多对一映射关系
property :需要处理多对一映射关系的属性名
javaType:该属性对应的那个实体类
在这里插入图片描述

3.分步查询
**1)**查询员工信息

/**
* 通过分步查询查询员工信息
* @param eid
* @return
*/
Emp getEmpByStep(@Param("eid") int eid);

/**

  • 通过分步查询查询员工信息
  • @param eid
  • @return
    */
    Emp getEmpByStep(@Param(“eid”) int eid);
<resultMap id="empDeptStepMap" type="Emp">
<id column="eid" property="eid"></id>
<result column="ename" property="ename"></result>
<result column="age" property="age"></result>
<result column="sex" property="sex"></result>
<!--
select:设置分步查询,查询某个属性的值的sql的标识(namespace.sqlId)
column:将sql以及查询结果中的某个字段设置为分步查询的条件
-->
<association property="dept"
select="com.atguigu.MyBatis.mapper.DeptMapper.getEmpDeptByStep" column="did">
</association>
</resultMap>
<!--Emp getEmpByStep(@Param("eid") int eid);-->
<select id="getEmpByStep" resultMap="empDeptStepMap">
select * from t_emp where eid = #{eid}
</select>

**2)**根据员工所对应的部门id查询部门信息

/**
* 分步查询的第二步:根据员工所对应的did查询部门信息
* @param did
* @return
*/
Dept getEmpDeptByStep(@Param("did") int did);
<!--Dept getEmpDeptByStep(@Param("did") int did);-->
<select id="getEmpDeptByStep" resultType="Dept">
select * from t_dept where did = #{did}
</select>

分步查询的优点:可以实现延迟加载,但是必须在核心配置文件中设置全局配置信息:
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。 否则,每个
属性会按需加载
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和
collection中的fetchType属性设置当前的分步查询是否使用延迟加载,fetchType=“lazy(延迟加
载)|eager(立即加载)”

一对多查询
根据部门id查新部门以及部门中的员工信息、一个部门有多个员工

使用collection标签
1.目的:设置字段和属性的映射关系
2.通过ofType获取集合里存储的数据类型
3.然后根据这个类型获取相应的属性
4.映射关系建立后,创建该类型的对象(此处是emp)
5.最后把每一个对象放在集合 emps中

/**
* 根据部门id查新部门以及部门中的员工信息
* @param did
* @return
*/
Dept getDeptEmpByDid(@Param("did") int did);
<resultMap id="deptEmpMap" type="Dept">
<id property="did" column="did"></id>s
<result property="dname" column="dname"></result>
<!--
ofType:设置collection标签所处理的集合属性中存储数据的类型
-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid"></id>
<result property="ename" column="ename"></result>
<result property="age" column="age"></result>
<result property="sex" column="sex"></result>
</collection>
</resultMap>
<!--Dept getDeptEmpByDid(@Param("did") int did);-->
<select id="getDeptEmpByDid" resultMap="deptEmpMap">
select dept.*,emp.* from t_dept dept left join t_emp emp on dept.did =
emp.did where dept.did = #{did}
</select>

collection:处理一对多的映射关系
ofType 表示该属性所对应的集合中存储数据的类型

分布查询

分布查询第一步: 查询部门信息

/**
* 分步查询部门和部门中的员工
* @param did
* @return
*/
Dept getDeptByStep(@Param("did") int did);

<resultMap id="deptEmpStep" type="Dept">
<id property="did" column="did"></id>
<result property="dname" column="dname"></result>
<collection property="emps" fetchType="eager"
select="com.atguigu.MyBatis.mapper.EmpMapper.getEmpListByDid" column="did">
</collection>
</resultMap>
<!--Dept getDeptByStep(@Param("did") int did);-->
<select id="getDeptByStep" resultMap="deptEmpStep">
select * from t_dept where did = #{did}
</select>
-->

2)根据部门id查询部门中的所有员工

/**
* 根据部门id查询员工信息
* @param did
* @return
*/
List<Emp> getEmpListByDid(@Param("did") int did);
<!--List<Emp> getEmpListByDid(@Param("did") int did);-->
<select id="getEmpListByDid" resultType="Emp">
select * from t_emp where did = #{did}
</select>

八、动态SQL

1.if :根据标签中的test属性所对应的表达式决定标签中的内容是否需要拼接到sql中

	<select id="getEmpByCondition" resultType="Emp">

		select * from t_emp where 1=1
		<if test="empName !=null and empName!='' ">
			and emp_name=#{empName}

		</if>
		<if test="age !=null and  age!=''">
			and age=#{age}
		</if>
		<if test="sex !=null and  sex!=''">
			and sex=#{sex}
		</if>
		<if test="email !=null and  email!=''">
			and email=#{email}
		</if>
	</select>

where 当where 有内容时会自动生成where关键字,并且将内容前多余的and 或or 去掉
当where标签中没有内容时,此时where 标签没有任何效果
where 标签不能将其中内容后面多余的and 或or 去掉

<select id="getEmpByCondition" resultType="Emp">

		select * from t_emp 
	 <where> 
	 	<if test="empName !=null and empName!='' ">
			and emp_name = #{empName}

		</if>
		<if test="age !=null and  age!=''">
			and age=#{age}
		</if>
		<if test="sex !=null and  sex!=''">
			and sex=#{sex}
		</if>
		<if test="email !=null and  email!=''">
			and email=#{email}
		</if>
	 </where>
	</select>

3.trim

prefix: 将trim 标签中内容前面添加指定内容
suffix:将trim 标签中内容后面添加指定内容
suffixOverrides : 将trim标签后面指定内容去掉

prefixOverrides:将trim标签前面指定内容去掉
若 trim 标签中没有内容时,trim标签也没有任何效果

<select id="getEmpByCondition" resultType="Emp">

		select * from t_emp 
	<trim prefix="where"  suffixOverrides="and|or">
	 	<if test="empName !=null and empName!='' ">
			 emp_name = #{empName} and

		</if>
		<if test="age !=null and  age!=''">
			 age=#{age}  and
		</if>
		<if test="sex !=null and  sex!=''">
			 sex=#{sex}  and
		</if>
		<if test="email !=null and  email!=''">
			 email=#{email}
		</if>
	 </trim>

4.choose when otherwise 相当于 if …else if…else
when 标签中有一个成立则其他when标签里的内容不会继续拼接
若都不成立 可以执行 otherwise 标签内的内容
when 标签至少有一个 otherwise至多有一个

<select id="getEmpByChoose"  resultType="Emp">

select * from t_emp 
<where>
   <choose>
     	<when test="empName !=null and empName!='' ">
     	  emp_name = #{empName}
     	</when>
     	     	<when test="empName !=null and empName!='' ">
     	  age = #{age}
     	</when>
     	     	<when test="empName !=null and empName!='' ">
     	 sex = #{sex}
     	</when>
     	     	<when test="empName !=null and empName!='' ">
     	  email = #{email}
     	</when>
     	<otherwise>
     	 did =1
     	</otherwise>
   </choose>
<!--实现动态修改-->
    <update id="updateUser">
        update user
        <set>
            <if test="username!=null and username!=''">
                username=#{username},
            </if>
            <if test="sex!=null and sex!=''">
                sex=#{sex},
            </if>
            <if test="phone!=null and phone!=''">
                phone=#{phone},
            </if>
        </set>
        where id=#{id}
    </update>

5.foreach标签
属性:
collection:设置要循环的数组或集合
item:表示集合或数组中的每一个数据
separator:设置循环体之间的分隔符
open:设置foreach标签中的内容的开始符
close:设置foreach标签中的内容的结束符
用foreach实现批量删除

int deleteMoreByArray(@Param("eids")Integer [] eids);

<delete id="deleteMoreByArray">

delete from t_emp where eid in
  <foreach collection="eids" item="eid" 
   separator="," open="(" close=")">
          ${eid}
   </foreach>
</delete>
<delete id="deleteMoreByArray">

delete from t_emp where 
  <foreach collection="eids" item="eid" separator="or">
        eid=${eid}
   </foreach>
</delete>

批量添加

<insert id="insertMoreEmp">
insert into t_emp values
<foreach collection="emps" item="emp" separator=",">
(null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null)
</foreach>
</insert>

6、SQL片段
sql片段,可以记录一段公共sql片段,在使用的地方通过include标签进行引入

<sql id="empColumns">
eid,ename,age,sex,did
</sql>
select <include refid="empColumns"></include> from t_emp

九、MyBatis的缓存

1、MyBatis的一级缓存
一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就
会从缓存中直接获取,不会从数据库重新访问
使一级缓存失效的四种
使一级缓存失效的四种情况:

  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存情况:

2、MyBatis的二级缓存
二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被
缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取
二级缓存开启的条件:
a>在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置
b>在映射文件中设置标签< cache />
c>二级缓存必须在SqlSession关闭或提交之后有效
d>查询的数据所转换的实体类类型必须实现序列化的接口
使二级缓存失效的情况:
两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

3、二级缓存的相关配置
在mapper配置文件中添加的cache标签可以设置一些属性:
eviction属性:缓存回收策略
LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。
FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
flushInterval属性:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size属性:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readOnly属性:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了
很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是
false。
4、MyBatis缓存查询的顺序
先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。
如果二级缓存没有命中,再查询一级缓存
如果一级缓存也没有命中,则查询数据库
SqlSession关闭之后,一级缓存中的数据会写入二级缓存
5、整合第三方缓存EHCache

添加依赖

<!-- Mybatis EHCache整合包 -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>

c>创建EHCache的配置文件ehcache.xml

<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
	<!-- 磁盘保存路径 -->
	<diskStore path="D:\atguigu\ehcache" />
	<defaultCache maxElementsInMemory="1000"
		maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true"
		timeToIdleSeconds="120" timeToLiveSeconds="120"
		diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
	</defaultCache>
</ehcache>

设置二级缓存的类型
在要开启的mapper.xml中设置

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

加入logback日志
存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。
创建logback的配置文件logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
	<!-- 指定日志输出的位置 -->
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>

			<pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger]
				[%msg]%n</pattern>
		</encoder>
	</appender>

	<root level="DEBUG">

		<appender-ref ref="STDOUT" />
	</root>
	<!-- 根据特殊需求指定局部日志级别 -->
	<logger name="com.atguigu.crowd.mapper" level="DEBUG" />
</configuration>

十、MyBatis的逆向工程

正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程
的。
逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源:
Java实体类
Mapper接口
Mapper映射文件

1、创建逆向工程的步骤
a>添加依赖和插件

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

	<dependencies>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.7</version>
		</dependency>
		<dependency>
<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>
<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.11</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.11</version>
					</dependency>
				</dependencies>
			</plugin>
		</plugins>
	</build>

b>创建MyBatis的核心配置文件
c>创建逆向工程的配置文件

注意!
文件名必须是: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: 生成基本的CRUD(清新简洁版) MyBatis3: 
		生成带条件的CRUD(奢华尊享版) -->
	<context id="DB2Tables" targetRuntime="MyBatis3Simple">
		<!-- 数据库的连接信息 -->
		<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/mybatis?&amp;useSSL=false&amp;serverTimezone=UTC&amp;characterEncoding=utf-8" 
			userId="root"
			password="root">
		</jdbcConnection>
		<!-- javaBean的生成策略 -->
		<javaModelGenerator targetPackage="com.ycx.pojo"
			targetProject=".\src\main\java">
			<property name="enableSubPackages" value="true" />
			<property name="trimStrings" value="true" />
		</javaModelGenerator>
		<!-- SQL映射文件的生成策略 -->
		<sqlMapGenerator targetPackage="com.ycx.mapper"
			targetProject=".\src\main\resources">
			<property name="enableSubPackages" value="true" />
		</sqlMapGenerator>
		<!-- Mapper接口的生成策略 -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="com.ycx.mapper" targetProject=".\src\main\java">
			<property name="enableSubPackages" value="true" />
		</javaClientGenerator>
		<!-- 逆向分析的表 -->
		<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
		<!-- domainObjectName属性指定生成出来的实体类的类名 -->
		<table tableName="t_emp" domainObjectName="Emp" />
		<table tableName="t_dept" domainObjectName="Dept" />
	</context>
</generatorConfiguration>

执行
在这里插入图片描述
没有的话在
在这里插入图片描述
填入在这里插入图片描述
在这里插入图片描述
QBC查询

@Test
public void testMBG() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSession sqlSession = new
SqlSessionFactoryBuilder().build(is).openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
EmpExample empExample = new EmpExample();
//创建条件对象,通过andXXX方法为SQL添加查询添加,每个条件之间是and关系
empExample.createCriteria().andEnameLike("a").andAgeGreaterThan(20).andDidIsNot
Null();
//将之前添加的条件通过or拼接其他条件
empExample.or().andSexEqualTo("男");
List<Emp> list = mapper.selectByExample(empExample);
for (Emp emp : list) {
System.out.println(emp);
}
}

十一 、分页插件

1.添加依赖

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>

配置分页插件
在MyBatis的核心配置文件中配置插件(标签有顺序)
在这里插入图片描述

<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

使用Mybatis的分页插件实现分页功能
1.需要在查询功能之前开启分页
PageHelper.startPage(int pageNum,int pageSize);

常用数据:
pageNum:当前页的页码
pageSize:每页显示的条数
size:当前页显示的真实条数
total:总记录数
pages:总页数
prePage:上一页的页码
nextPage:下一页的页码
常用数据:
pageNum:当前页的页码
pageSize:每页显示的条数
size:当前页显示的真实条数
total:总记录数
pages:总页数
prePage:上一页的页码
nextPage:下一页的页码
在这里插入图片描述
若还有没有的数据则使用
在这里插入图片描述
其中的 第一个参数是 查询出来的表的集合(分页数据) 第二个参数是 你想展示的导航页码 建议奇数

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值