mybatis基础操作(三)

动态sql

通过动态sql实现多条件查询,这里以查询为例,实现动态sql的书写。

创建members表

创建表并插入数据:

create table members (member_id int (11),member_nick varchar (60),member_gender char (15),member_age int (11),member_city varchar (90)
); 
insert into members (member_id, member_nick, member_gender, member_age, member_city) values('1','reading','W','99','wuhan');
insert into members (member_id, member_nick, member_gender, member_age, member_city) values('2','running','W','32','changsha');
insert into members (member_id, member_nick, member_gender, member_age, member_city) values('3','talking','W','26','changsha');
insert into members (member_id, member_nick, member_gender, member_age, member_city) values('4','song','W','22','beijing');
insert into members (member_id, member_nick, member_gender, member_age, member_city) values('5','running','F','28','beijing');
commit;

创建对应的members类

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Members implements Serializable {private int memberId;private String memberNick;private String memberGender;private int memberAge;private String memberCity;
}

创建对应的dao类

public interface MembersDao {public List<Members> queryMemberUsingWhere(HashMap<String, Object> parms);public List<Members> queryMemberUsingTrim(HashMap<String, Object> parms);public List<Members> queryMemberByCity(List<String> cities);public List<Members> queryMemberByNick(String keyword);public Members queryMemberById(int id);public int updateMember(@Param("id") int id, @Param("age") int age);
}

创建xml文件

编写MembersDao的map文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kingyal.dao.MembersDao"><!--    -->
<!--    <cache readOnly="true" size=""></cache>--><resultMap id="MemberMapper" type="Members"><id column="member_id" property="memberId"></id><result column="member_nick" property="memberNick"></result><result column="member_gender" property="memberGender"></result><result column="member_age" property="memberAge"></result><result column="member_city" property="memberCity"></result></resultMap><select id="queryMemberUsingWhere" resultMap="MemberMapper">select member_id,member_nick,member_gender,member_age,member_cityfrom members<!--where 自动识别and --><where><!--gender 为参数对象的属性或者是map中的key值 --><if test="gender != null">and member_gender = #{gender}</if><!-- &gt; 表示大于 --><if test="minAge != null">and member_age &gt;= #{minAge}</if><!-- &lt; 表示小于 --><if test="maxAge != null">and member_age &lt;= #{maxAge}</if><if test="city != null">and member_city = #{city}</if></where></select><select id="queryMemberUsingTrim" resultMap="MemberMapper">select member_id,member_nick,member_gender,member_age,member_cityfrom members<!--trim: 起补充作用prefix:sql增加前缀prefixOverrides:如果第一个条件中有and或者or,将会去除掉suffix: sql增加后缀--><trim prefix="where" prefixOverrides="and | or" suffix="order by member_age"><!--gender 为参数对象的属性或者是map中的key值 --><if test="gender != null">and member_gender = #{gender}</if><!-- &gt; 表示大于 --><if test="minAge != null">and member_age &gt;= #{minAge}</if><!-- &lt; 表示小于 --><if test="maxAge != null">and member_age &lt;= #{maxAge}</if><if test="city != null">and member_city = #{city}</if></trim></select><select id="queryMemberByCity" resultMap="MemberMapper">select member_id,member_nick,member_gender,member_age,member_cityfrom memberswhere member_city in<!--collection:指定集合的类型,这里的list实际上是com.java.util.List,在mybatis中做了映射item:值的别名,在配置中需要用到seperator:每个值之间的分隔符open:以(开头close:以)开头最终达到以下效果:(changsah, beijing1)--><foreach collection="list" item="cityName" separator="," open="(" close=")">#{cityName}</foreach></select><!--${key}:表示获取参数,先获取参数的值拼接到sql中,再编译sql,会有sql注入问题,写法:where member_nick like '%${keyword}%'#{key}:表示获取参数,先编译sql,再将获取到的参数值拼接到sql中,写法:where member_nick like CONCAT('%',#{keyword},'%')--><select id="queryMemberByNick" resultMap="MemberMapper">select member_id,member_nick,member_gender,member_age,member_cityfrom memberswhere member_nick like CONCAT('%',#{keyword},'%')</select><select id="queryMemberById" resultMap="MemberMapper" useCache="true">select member_id,member_nick,member_gender,member_age,member_cityfrom memberswhere member_id=#{id}</select><update id="updateMember" flushCache="true">update members set member_age=#{age} where member_id=#{id};</update>
</mapper>

将类名与实体进行映射:

在这里插入图片描述

将membersDao的map文件添加到mybatis配置中:
在这里插入图片描述

编写demo

public class MembersDaoTest {@Testpublic void queryMemberUsingWhere() {HashMap<String, Object> params = new HashMap<String, Object>();params.put("gender", "W");params.put("minAge", 20);params.put("maxAge", 40);params.put("city", "changsha");MembersDao membersDao = MybatisUtil.getMapper(MembersDao.class);List<Members> membersList = membersDao.queryMemberUsingWhere(params);for (Members m : membersList) {System.out.println(m);}}@Testpublic void queryMemberUsingTrim() {HashMap<String, Object> params = new HashMap<String, Object>();params.put("gender", "W");params.put("minAge", 20);params.put("maxAge", 40);params.put("city", "changsha");MembersDao membersDao = MybatisUtil.getMapper(MembersDao.class);List<Members> membersList = membersDao.queryMemberUsingTrim(params);for (Members m : membersList) {System.out.println(m);}}@Testpublic void queryMemberByCity() {List<String> cities = new ArrayList<String>();cities.add("changsha");cities.add("beijing");MembersDao membersDao = MybatisUtil.getMapper(MembersDao.class);List<Members> membersList = membersDao.queryMemberByCity(cities);for (Members m : membersList) {System.out.println(m);}}@Testpublic void queryMemberByNick() {MembersDao membersDao = MybatisUtil.getMapper(MembersDao.class);List<Members> membersList = membersDao.queryMemberByNick("r");for (Members m : membersList) {System.out.println(m);}}
}

mybatis日志记录

常见的日志记录组件有log4j,log4j2等,mybatis内部采用log4j组件。通过日志,可以查看sql执行情况。如下是配置方式。

引入pom文件

在这里插入图片描述

在resource目录下创建log4j.properties文件

在这里插入图片描述

如下是配置内容:

# 输出debug信息到控制台
log4j.rootLogger=DEBUG,stdout
# 日志级别
log4j.logger.org.mybatis.example.BlogMapper=TRACE
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
# 日志的打印格式 %t:线程名称 %5p:日志级别 %n:换行 %msg:打印内容 %n:换行
log4j.appender.stdout.layout.ConversionPattern=[%t] %5p - {%msg} %n

mybatis启动时打印日志

在这里插入图片描述

配置第三方数据库连接池

在进行数据库操作时,mybatis支持基于数据库连接池的方式。mybatis的配置中,有一个dataSource标签:
在这里插入图片描述

如果type标签的属性值为POOLED,表示使用mybatis内置的连接池管理;如果想使用第三方的数据库连接池,需要进行自定义配置。

druid连接池的配置方式

引入pom文件
在这里插入图片描述

mybatis缓存

mybatis使用缓存机制,优化查询性能。第一次查询到的数据会放置在缓存中,第二次查询时会优先到缓存中查询,如果缓存中没有,就会到数据库查询,在数据库中查到后,同时存储到缓存中。

一级缓存

为sqlsession对象建立的缓存,每个sqlsession有单独的缓存,无需手动开启,可直接使用,多个sqlsession无法共享。如果sqlsession关闭或者清空缓存,就会重新从数据库获取数据。如果第一次查询完成后,对查询出的对象做修改,第二次查询会直接使用缓存,查询出的结果为修改后的值。如果第一次查询后,使用这个个sqlsession执行了update操作,此操作在更新数据库的同时,也会更新缓存,第二次查询出的结果为修改后的值。demo如下:

public void queryMemberByNickToTestFirstCache() {SqlSession sqlSession = MybatisUtil.getSqlSession();MembersDao membersDao = sqlSession.getMapper(MembersDao.class);List<Members> membersList1 = membersDao.queryMemberByNick("reading");System.out.println(membersList1);System.out.println("~~~~~~~~~~~~~~~不会查询数据库,直接从缓存获取数据~~~~~~~~~~~~");MembersDao membersDao2 = sqlSession.getMapper(MembersDao.class);List<Members> membersList2 = membersDao2.queryMemberByNick("reading");System.out.println(membersList2);
}public void queryMemberByNickToTestFirstCacheCelaning() {SqlSession sqlSession = MybatisUtil.getSqlSession();MembersDao membersDao = sqlSession.getMapper(MembersDao.class);List<Members> membersList1 = membersDao.queryMemberByNick("reading");System.out.println(membersList1);// 清理缓存sqlSession.clearCache();System.out.println("~~~~~~~~~~~~~~~缓存被清空,再次查询会访问数据库~~~~~~~~~~~~");MembersDao membersDao2 = sqlSession.getMapper(MembersDao.class);List<Members> membersList2 = membersDao2.queryMemberByNick("reading");System.out.println(membersList2);
}public void queryMemberByIdToTestFirstCacheChangingAge() {SqlSession sqlSession = MybatisUtil.getSqlSession();MembersDao membersDao = sqlSession.getMapper(MembersDao.class);Members members1 = membersDao.queryMemberById(1);System.out.println(members1);members1.setMemberAge(60);System.out.println("~~~~~~~~~~~~~~~没有清理缓存,第二次查询时,age变成了60~~~~~~~~~~~~");MembersDao membersDao2 = sqlSession.getMapper(MembersDao.class);Members members2 = membersDao2.queryMemberById(1);System.out.println(members2);}public void updateMemberToTestFirstCacheChangingAge() {SqlSession sqlSession = MybatisUtil.getSqlSession();MembersDao membersDao1 = sqlSession.getMapper(MembersDao.class);Members members1 = membersDao1.queryMemberById(1);System.out.println(members1);//  做了更新操作membersDao1.updateMember(1, 99);sqlSession.commit();System.out.println("~~~~~~~~~~~~~~~在第一次查询后,使用代码更新了数据库,缓存也会被同步更新,第二次查询为99~~~~~~~~~~~~");MembersDao membersDao2 = sqlSession.getMapper(MembersDao.class);Members members2 = membersDao2.queryMemberById(1);System.out.println(members2);}

二级缓存

​ 二级缓存也称为sqlSessionFactory级缓存,通过同一个factory对象获取的SqlSession可以共享二级缓存,在应用服务器中,SqlSessionFactory是单例的,因此,我们二级缓存可以实现全局共享。特性如下:

​ 1. 二级缓存默认没有开启,需要在mybatis的配置文件中的settgng标签开启。
在这里插入图片描述
​ 2. 并在需要使用二级缓存的mapper文件中配置cache标签,表示使用二级缓存。
在这里插入图片描述

​ eviction策略:
在这里插入图片描述
​ flushInterval:刷新间隔,设置的值是一个以毫秒为单位的合理时间量,默认不设置,此时缓存仅仅会在调用语句时刷新。
​ size:引用数目,表示缓存的大小,设置时要注意缓存对象的大小和此时的可用内存,默认是1024。
​ readOnly:属性可以设置为true或者false,true表示只读,只读的缓存会给所有调用者返回缓存对象的相同实例。因为他们不能被修改。false表示可读写,可读写的缓存会通过序列化返回缓存对象的拷贝,速度上会慢一些,但是更安全,默认是false。
​ 3. 二级缓存只能缓存实现序列化接口的对象。
实例:

public void queryMemberByIdToTestSecondCacheChangingAge() {SqlSessionFactory factory= MybatisUtil.getSqlSessionFactory();SqlSession sqlSession = factory.openSession();MembersDao membersDao = sqlSession.getMapper(MembersDao.class);Members members1 = membersDao.queryMemberById(1);System.out.println(members1);sqlSession.commit();System.out.println("~~~~~~~~~~~~~commit之后,就会将当前sqlsession的查询结果缓存到二级缓存~~~~~~~~~~~~~~");SqlSession sqlSession2 = factory.openSession();MembersDao membersDao2 = sqlSession2.getMapper(MembersDao.class);Members members2 = membersDao2.queryMemberById(1);System.out.println(members2);
}

也可以在查询时使用二级缓存:

​ 1. 使用“flushCache”表示做更新操作时刷新缓存:
在这里插入图片描述
2. 使用“useCache”表示做查询操作时使用缓存
在这里插入图片描述

延迟加载

如果在mybatis开启了延迟加载,在执行子查询时(至少查询两次及以上),默认只执行第一次查询,当用到子查询的查询结果时,才会触发子查询的执行;如果无需用到子查询结果,则子查询不会执行。延迟加载的作用是减少对数据库的访问。配置如下,在子查询语句中配置fetchType为“true”.

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/535332.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么时候去检测大数据信用风险比较合适?

什么时候去检测大数据信用风险比较合适?在当今这个数据驱动的时代&#xff0c;大数据信用风险检测已经成为个人的一项重要需求。本文将从贷前检测、信息泄露检测和定期检测三个方面&#xff0c;阐述何时进行大数据信用风险检测较为合适。 一、贷前检测 大数据信用风险检测在贷…

指针【理论知识速成】(3)

一.指针的使用和传值调用&#xff1a; 在了解指针的传址调用前&#xff0c;先来额外了解一下 “传值调用” 1.传值调用&#xff1a; 对于来看这个帖子的你相信代码展示胜过千言万语 #include <stdio.h> #include<assert.h> int convert(int a, int b) {int c 0…

【Python】python实现Apriori算法和FP-growth算法(附源代码)

使用一种你熟悉的程序设计语言&#xff0c;实现&#xff08;1&#xff09;Apriori算法和&#xff08;2&#xff09;FP-growth算法。 目录 1、Apriori算法2、F-Growth算法3、两种算法比较 1、Apriori算法 def item(dataset): # 求第一次扫描数据库后的 候选集&#xff0c;&am…

OpenCASCADE开发指南<四>:OCC 数据类型和句柄

一个软件首先要规定能处理的数据类型&#xff0c; 其次要实现三项最基本的功能——引用管理、内存管理和异常管理。在 OCC 中&#xff0c;这三项功能分别对应基础类中的句柄、内存管理器和异常类。 1 数据类型 在基本概念篇里&#xff0c;已经介绍了 OCC 数据类型的分类&…

Linux:好用的Linux指令

进程的Linux指令 1.查看进程信息 ​​​​ps ajx | head -1 && ps ajx | grep 进程名创建一个进程后输入上述代码&#xff0c;会打印进程信息&#xff0c;当我们在code.exe中写入打印pid&#xff0c;ppid&#xff0c;这里也和进程信息一致。 while :; do ps ajx | he…

Python语言在编程业界的地位——《跟老吕学Python编程》附录资料

Python语言在编程业界的地位——《跟老吕学Python编程》附录资料 ⭐️Python语言在编程业界的地位2024年3月编程语言排行榜&#xff08;TIOBE前十&#xff09; ⭐️Python开发语言开发环境介绍1.**IDLE**2.⭐️PyCharm3.**Anaconda**4.**Jupyter Notebook**5.**Sublime Text** …

机器学习——过拟合问题、正则化解决法

过拟合的基本概念 欠拟合&#xff1a;假设函数没有很好的拟合训练集数据&#xff0c;也称这个假设函数有高偏差&#xff1b; 过拟合&#xff1a;过拟合也称为高方差。在假设函数中添加高阶多项式&#xff0c;让假设函数几乎能完美的拟合每个样本数据点&#xff0c;这看起来很…

使用ubuntu搭建hadoop伪分布全过程图解

目录 1. 安装jdk 2. 添加java环境变量 3. 设置免密登录 4. 安装hadoop 5. 添加hadoop环境变量 6. 修改hdoop-env.sh文件 7. 修改core-site.xml文件 8. 修改yarn-site.xml文件 9. 修改mapred-site.xml文件 10. 修改hdfs-site.xml文件 11. 进行授权 12. 创建namenode…

【论文精读】Transformer:Attention Is All You Need

《动手学深度学习》关于Transformer和注意力机制的笔记 李沐《动手学深度学习》注意力机制 文章目录 《动手学深度学习》关于Transformer和注意力机制的笔记一、文章概览&#xff08;一&#xff09;摘要&#xff08;二&#xff09;结论部分&#xff08;三&#xff09;引言&am…

java基础2-常用API

常用API Math类 帮助我们进行数学计算的工具类。 里面的方法都是静态的。 3.常见方法如下&#xff1a; abs:获取绝对值 absExact:获取绝对值 ceil:向上取整 floor:向下取整 round:四舍五入 max:获取最大值 …

第十四届蓝桥杯蜗牛

蜗牛 线性dp 目录 蜗牛 线性dp 先求到达竹竿底部的状态转移方程 求蜗牛到达第i根竹竿的传送门入口的最短时间​编辑 题目链接&#xff1a;蓝桥杯2023年第十四届省赛真题-蜗牛 - C语言网 关键在于建立数组将竹竿上的每个状态量表示出来&#xff0c;并分析出状态转移方程 in…

游泳防水耳机排名,高性价比国际游泳耳机品牌排行榜前十名

随着科技的飞速发展&#xff0c;运动游泳耳机已经成为当代运动时尚和游泳爱好者的必备装备之一。在游泳训练或是户外运动时&#xff0c;一款高性价比的游泳耳机不仅能带给我们高品质的音乐体验&#xff0c;还能有效防水防汗&#xff0c;陪伴我们享受运动带来的乐趣。为了帮助大…