动态SQL
当需求是可能存在0到多个条件进行sql查询时,需要进行sql条件拼接。使用java过于繁琐,在mybatis有如下的解决方案。
1.使用if标签进行拼接
select * from table where 1=1
<if test=" name != null and name != ' ' ">
and name=#{name}
</if>
2.使用where标签
在where标签内使用if标签,where可以自动处理if标签前面多余的and以及是否生成where。
但是不能将if标签后面的and截取掉!!!!!
select * from table
<where>
<if test=" name != null and name != ' ' ">
name=#{name}
</if>
<if test=" age!= null and age!= ' ' ">
and age=#{age}
</if>
</where>
3.trim标签
trim标签有四个属性,prefix、suffix表示整体的前后添加指定字符串,prefixOverrides、suffixOverrides表示整体标签的前后去掉指定字符串。
select * from table
<trim prefix="where" suffixOverrides="and">
<if test=" name != null and name != ' ' ">
name=#{name} and
</if>
<if test=" age!= null and age!= ' ' ">
age=#{age} and
</if>
</trim>
4.choose when otherwise标签
类似switch
select * from table
<where>
<choose>
<when test=" name != null and name != ' ' ">
name=#{name}
</when>
<when test=" age!= null and age!= ' ' ">
age=#{age}
</when>
</choose>
</where>
5.foreach标签
void insertMoreEmp(@param("emps")List<Emp>emps);
<insert id="insertMoreEmp">
insert into emp values
<foreach collection="emps" item="emp" separator=",">
(null,#(emp.empName),#{emp.age},#{emp.gender},null)
</foreach>
</insert>
注意:
当输入参数为List时,取参数需要用list,所以最好用注解标注参数名字
foreach标签有分隔符属性,在每个元素中间隔开
<delete id = "deleteMoreEmp">
delete from emp where id in
(
<foreach collection="empIds" item="empId" separator=",">
#{empId}
</foreach>
)
<foreach collection="empIds" item="empId" separator="," open="(" close=")">
#{empId}
</foreach>
</delete>
<delete id = "deleteMoreEmp">
delete from emp where
<foreach collection="empIds" item="empId" separator="or">
emp_id = #{empId}
</foreach>
</delete>
6.sql标签
<sql id="empColumns">
emp_id,emp_name,age,gender,dept_id
</sql>
<select id="func">
select <include refid="empColumns"/> from emp
</select>
Mybatis的缓存
Mybatis的一级缓存
Mybatis的一级缓存为SqlSession级别的,即通过一个SqlSession查询的数据会被缓存
当使用同一个session查询同一条数据时会从缓存中获取
默认开启
一级缓存失效的情况:
不同的SqlSession
不同的数据
查询之间执行过增删改操作,会清空缓存
查询之间手动清空过缓存 sqlSession.clearCache();
Mybatis的二级缓存
Mybatis的二级缓存为SqlSessionFactory级别的,即通过同一个Factory创建的Session查询的结果会被缓存
使用相同Factory创建的Session查询数据会从缓存中获取
开启条件:
在核心配置文件中设置 cacheEnabled="true" ,默认为true
在映射文件中设置标签<cache/>
二级缓存必须在Session关闭或提交后有效
查询的数据所转换的实体类类型必须实现序列化的接口 implements Serializable
失效:
增删改操作
手动清除一级缓存不会影响二级
二级缓存的配置
1.eviction 缓存回收策略 默认LRU
LRU 最近最少使用
FIFO 队列
SOFT 软引用 移除基于垃圾回收器状态和软引用规则的对象
WEAK 弱引用 更积极地移除基于垃圾回收器状态和弱引用规则的对象
2.flushInterval 刷新间隔 单位为毫秒
默认为不设置,当语句调用时刷新
3.size 引用数目
代表缓存最多储存多少个对象
4.readOnly只读 默认false
当为true时会直接返回缓存中的对象,若进行修改则会导致下次的查询结果有问题,性能优势
false时会创建一个副本,修改不会对缓存中的内容产生影响,安全
Mybatis缓存查询的顺序
先查询二级缓存,没有命中再查询一级,没有命中则查询数据库。
整合第三方缓存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>
ehcache依赖于slf4j,slf4j是接口也叫做门面,logback-classic是该门面的实现
配置文件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:\dev\ehcache"/> <defaultCache maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true" timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
</defaultCache> </ehcache>
设置二级缓存类型
不设置时为内置的
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
Mybatis的逆向工程
正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。 Hibernate是支持正向工程的。
逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成:
依赖
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.7</version> </dependency> <!-- junit测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- log4j日志 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</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> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> </dependencies> </plugin> </plugins> </build>
创建逆向工程核心配置文件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="MyBatis3"> <!-- 数据库的连接信息 --> <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis? serverTimezone=UTC" userId="root" password="123456">
<property name="nullCatalogMeansCurrent" value="true" />
</jdbcConnection> <!-- javaBean的生成策略--> <javaModelGenerator targetPackage="com.atguigu.mybatis.pojo" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- SQL映射文件的生成策略 --> <sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- Mapper接口的生成策略 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.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>
配置正确后,在数据库有对应表的情况下,点击插件generator就可以自动生成代码
分页插件
依赖
分页拦截器
会自动拦截sql返回的结果,使结果返回的是对应页的结果。
查询前使用PageHelper.startPage(PageNum,PageSize)
该方法有返回值Page<Object> page
page中会自动保存后续查到的部分信息。
mapper查询结果的返回值也可以设置为page类型
查询后使用PageInfo<Emp> pageInfo = new PageInfo<>(list,导航分页页码数)
pageInfo数据更丰富更多。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!