1、持久化和ORM
-
持久化:从瞬时到持久 又从 持久到瞬时 的一个过程 称为持久化
-
ORM:定义 : 对象关系映射 Object、 Relational Mapper Mybatis属于半自动化的ORM框架
mapper.xml--->实体类 mybatis 核心 mybatis
2、核心对象
1、SqlSessionFactory (SQL会话工厂)
用于创建SqlSession对象。它是一个线程安全的对象,一般在应用程序启动时创建并保持单例。SqlSessionFactory负责读取并解 析MyBatis的配置文件,建立数据库连接池,并管理各种资源和插件,以便为应用程序提供SqlSession实例。
作用域:全局
生命周期:跟应用的生命周期相同
2、SqlSessionFactoryBuild (SQL会话工厂构建器)
SqlSessionFactoryBuilder是用于创建SqlSessionFactory的构建器对象。它负责读取MyBatis的配置文件,并根据配置信息构建 SqlSessionFactory对象。一般情况下,SqlSessionFactoryBuilder是一个临时对象,用完后可以丢弃。
作用域:局部
生命周期:只限于方法体内
3、SqlSession(SQL会话)
SqlSession是与数据库交互的主要接口对象。它提供了执行SQL语句、提交事务、获取Mapper接口实例等操作。SqlSession是 一个轻量级的非线程安全对象,每个线程都应该拥有自己的SqlSession实例,用完后需要手动关闭。
SqlSession通过SqlSessionFactory创建,并使用SqlSessionFactory管理数据库连接。
作用域:一次请求 request 一次会话
生命周期:一次会话
示例:
// 1. 创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2. 创建SqlSessionFactory对象
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 3. 创建SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4. 执行sql
int count = sqlSession.insert("insertCar"); // 这个"insertCar"必须是sql的id
System.out.println("插入几条数据:" + count);
// 5. 提交(mybatis默认采用的事务管理器是JDBC,默认是不提交的,需要手动提交。)
sqlSession.commit();
// 6. 关闭资源(只关闭是不会提交的)
sqlSession.close();
3、mybatis-config.xml配置文件
mybatis核心配置文件的文件名不一定是mybatis-config.xml,可以是其它名字。但是一般都是mybatis-config
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
-
configuration(配置)
-
properties(属性) 定义属性值,可以在配置文件中引用。常用于数据库连接信息的配置。
-
settings(设置) 用于设置全局属性,如缓存、延迟加载和日志等。
-
typeAliases(类型别名) 配置Java类的别名,用于简化映射文件中的类型引用。
-
typeHandlers(类型处理器) 自定义类型处理器,用于处理Java对象和数据库类型之间的转换。
-
objectFactory(对象工厂) 自定义对象工厂,用于创建结果对象的实例。
-
plugins(插件) 自定义插件,可在MyBatis执行过程中添加额外的功能。
-
environments(环境配置)配置不同的数据库环境,如开发、测试、生产环境。
-
environment(环境变量) 定义一个数据库环境。
-
transactionManager(事务管理器) 配置事务管理器,用于管理数据库事务。
-
dataSource(数据源)配置数据源,指定数据库连接信息。
-
-
-
databaseIdProvider(数据库厂商标识) 根据数据库厂商标识选择不同的SQL语句。
-
mappers(映射器) 加载映射器(Mapper)接口或映射文件。
-
1、properties属性
<properties resource="文件路径"/>
2、setting属性 logback.xml
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
autoMappingBehavior | 指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。 | NONE, PARTIAL, FULL | PARTIAL |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
3、类别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<typeAliases>
<paclkage name="实体类的包名"/>
</typeAliases>
4、环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema 的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
不过要记住:尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
注意一些关键点:
默认使用的环境 ID(比如:default="development")。 每个 environment 元素定义的环境 ID(比如:id="development")。 事务管理器的配置(比如:type="JDBC")。 数据源的配置(比如:type="POOLED")。 默认环境和环境 ID 顾名思义。 环境可以随意命名,但务必保证默认的环境 ID 要匹配其中一个环境 ID。
environments 元素定义了如何配置环境。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<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>
4、mapper.xml 映射文件
XML 映射器
MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
-
cache
– 该命名空间的缓存配置。 -
cache-ref
– 引用其它命名空间的缓存配置。 -
resultMap
– 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。 -
parameterMap
– 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。 -
sql
– 可被其它语句引用的可重用语句块。 -
insert
– 映射插入语句。 -
update
– 映射更新语句。 -
delete
– 映射删除语句。 -
select
– 映射查询语句。
1、查询select
多参入参
<sql id="baseColumn">
`id`
, `account`, `realName`, `password`, `sex`, `birthday`, `phone`, `address`, `roleId`, `createdUserId`, `caretedTime`, `updatedUserId`, `updatedTime`
</sql>
1、实体类
<select id="queryUserByNameAndPassword" resultType="pojo.SysUser" parameterType="pojo.SysUser">
select
<include refid="baseColumn"></include>
from t_sysuser
where realName = #{realName} and password = #{password}
</select>
2、map 要保证key值和#{名字}相同
<select id="queryUserByPasswordMap" resultType="pojo.SysUser" parameterType="java.util.Map">
select
<include refid="baseColumn"></include>
from t_sysuser
where realName = #{name} and password = #{pwd}
</select>
3、@Param 如果入参的列名 子啊实体里面没有就需要自己指定 保证@Param("") 和#{}名字一样
SysUser queryUserLimit(@Param("pageIndex") Integer pageIndex, @Param("pageSize") Integer pageSize);
<select id="queryUserLimit" resultType="pojo.SysUser">
select
<include refid="baseColumn"></include>
from t_sysuser
limit #{pageIndex},#{pageSize}
</select>
4、list 批量插入、删除
<!--动态SQL-->
<insert id="insertAuthor" useGeneratedKeys="true"
keyProperty="id">
insert into Author (username, password, email, bio) values
<foreach item="item" collection="list" separator=",">
(#{item.username}, #{item.password}, #{item.email}, #{item.bio})
</foreach>
</insert>
5、单个数据类型
<select id="getUserById" resultType="pojo.SysUser">
select *
from t_sysuser
<if test="id != null">
where id = #{id}
</if>
</select>
2、联表查询(ResultMap assicotion collection)
resultMap
元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets
数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap
能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
<!-- 非常复杂的结果映射 -->
<resultMap id="detailedBlogResultMap" type="Blog">
<constructor>
<idArg column="blog_id" javaType="int"/>
</constructor>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
<result property="password" column="author_password"/>
<result property="email" column="author_email"/>
<result property="bio" column="author_bio"/>
<result property="favouriteSection" column="author_favourite_section"/>
</association>
<collection property="posts" ofType="Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<association property="author" javaType="Author"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
</collection>
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>
结果映射(resultMap)
-
constructor
- 用于在实例化类时,注入结果到构造方法中
-
idArg
- ID 参数;标记出作为 ID 的结果可以帮助提高整体性能 -
arg
- 将被注入到构造方法的一个普通结果
-
-
id
– 一个 ID 结果;标记出作为 ID 的结果可以帮助提高整体性能 -
result
– 注入到字段或 JavaBean 属性的普通结果 -
association 一对多、多对一
– 一个复杂类型的关联;许多结果将包装成这种类型
-
嵌套结果映射 – 关联可以是
resultMap
元素,或是对其它结果映射的引用
-
-
collection 一对多
– 一个复杂类型的集合
-
嵌套结果映射 – 集合可以是
resultMap
元素,或是对其它结果映射的引用
-
-
discriminator
– 使用结果值来决定使用哪个
resultMap
-
case
– 基于某些值的结果映射
-
嵌套结果映射 –
case
也是一个结果映射,因此具有相同的结构和元素;或者引用其它的结果映射
-
-
3、动态SQL
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
-
if
-
choose (when, otherwise)
-
trim (where, set)
-
foreach
1、if+trim 查询 set+if+trim 修改
<if>:用于判断条件是否成立,如果条件成立,则包含在<if>
标签内的SQL语句会被包含在最终生成的SQL语句中
参数:test返回true/false
<trim>:用于去除多余的SQL语句片段,如去除不必要的
WHERE`关键字或逗号。
参数:
-
prefix
:指定在生成SQL语句片段前添加的内容。 -
suffix
:指定在生成SQL语句片段后添加的内容。 -
prefixOverrides
:指定需要去除的前缀内容。 -
suffixOverrides
:指定需要去除的后缀内容。
<set>
是MyBatis中的一个动态SQL元素,用于生成UPDATE语句中的SET子句。它可以根据条件动态生成需要更新的字段、没有参数
<select id="select" resultMap="select" parameterType="pojo.SysUser">
select us.account, us.realName, ro.roleName, us.sex, us.birthday, us.phone
from t_sysuser us
left join t_sysrole ro on us.roleId = ro.id
<trim prefix="where" prefixOverrides="and | or">
<if test="account != null and account != ''">
and us.account like "%"#{account}"%"
</if>
<if test="roleName != null and roleName != ''">
and ro.roleName = #{roleName}
</if>
</trim>
limit #{pageBegin}, #{pageSize}
</select>
<update id="updateUser">
UPDATE `yyds`.`t_sysuser`
<trim prefix="set" suffixOverrides="," suffix="where id = #{id}">
<if test="account != null and account != ''">
`account` = #{account},
</if>
<if test="realName != null and realName != ''">
`realName` = #{realName},
</if>
<if test="password != null and password != ''">
`password` = #{password},
</if>
<if test="sex != null">
`sex` = #{sex},
</if>
<if test="birthday != null">
`birthday` = #{birthday},
</if>
<if test="phone != null and phone != ''">
`phone` = #{phone},
</if>
<if test="address != null and address != ''">
`address` = #{address},
</if>
<if test="roleId != null">
`roleId` = #{roleId},
</if>
<if test="createdUserId != null">
`createdUserId` = #{createdUserId},
</if>
<if test="createdTime != null">
`createdTime` = #{createdTime},
</if>
<if test="updatedUserId != null">
`updatedUserId` = #{updatedUserId},
</if>
<if test="updatedTime != null">
`updatedTime` = #{updatedTime}
</if>
</trim>
</update>
bind
bind
元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
2、choose+otherwise+when查询
<select id="selectBySupNameOrSupCodeOrSupContactOrCreatedTime" resultType="pojo.Supplier">
select id, supCode, supName, supContact, supPhone, supFax, createdTime
from t_supplier
<where>
<choose>
<when test="supName != null and supName != ''">
and supName like "%"#{supName}"%"
</when>
<when test="supCode != null and supCode != ''">
and supCode like "%"#{supCode}"%"
</when>
<when test="supContact != null and supContact != ''">
and supContact like "%"#{supContact}"%"
</when>
<otherwise>
and createdTime = #{createdTime}
</otherwise>
</choose>
</where>
</select>
重点功能 联表 动态SQL foreach 核心对象 三个
在MyBatis中,可以使用<foreach>
动态SQL元素来处理联表查询的动态SQL语句。<foreach>
元素通常用于循环遍历一个集合或数组,并将集合中的元素动态地添加到SQL语句中。
<select id="getUserOrders" parameterType="User" resultType="Order">
SELECT *
FROM user u
JOIN orders o ON u.id = o.user_id
WHERE u.id IN
<foreach collection="userIds" item="userId" open="(" separator="," close=")">
#{userId}
</foreach>
</select>
最后这是我今天学习的分享:mybatis分页插件:PageHelper
PageHelper是MyBatis的一个分页插件,它提供了方便的分页查询功能,可以简化分页查询的开发过程。
使用PageHelper可以实现以下功能:
-
自动拦截SQL语句,根据传入的分页参数进行分页查询。 就可以不用在mapper.xml映射文件中写limit语句了
-
支持多种分页方式,如基于物理分页的
Page
对象、基于逻辑分页的PageInfo
对象等。 -
提供了丰富的分页参数设置和分页结果信息获取的方法。
-
可以与MyBatis的原生SQL语句、Mapper接口方法和XML映射文件无缝集成。
第一步:引入依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.1</version>
</dependency>
第二步:在mybatis-config.xml文件中配置插件
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
第三步:编写Java代码
接口:
List<Car> selectAll();
映射文件:
<select id="selectAll" resultType="pojo.Car">
select id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car
</select>
关键点:
-
在查询语句之前开启分页功能。
-
在查询语句之后封装PageInfo对象。(PageInfo对象将来会存储到request域当中。在页面上展示。)
测试类:
@Test
public void pageHelper() {
SqlSession sqlSession = SqlSessionUtil.openSession();
paging mapper = sqlSession.getMapper(paging.class);
int pageNum = 1;
int pageSize = 3;
// 开启分页
PageHelper.startPage(pageNum,pageSize);
// 执行查询语句
List<Car> cars = mapper.selectAll();
// 获取分页信息对象
PageInfo<Car> carPageInfo = new PageInfo<>(cars,3);
System.out.println(carPageInfo);
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
执行结果:
PageInfo{pageNum=1, pageSize=3, size=3, startRow=1, endRow=3, total=24, pages=8, list=Page{count=true, pageNum=1, pageSize=3, startRow=0, endRow=3, total=24, pages=8, reasonable=false, pageSizeZero=false}[Car(id=1, carNum=1001, brand=宝马520Li, guidePrice=10.0, produceTime=2022-09-01, carType=燃油车), Car(id=2, carNum=1002, brand=奔驰E300E, guidePrice=55.0, produceTime=2022-11-11, carType=新能源), Car(id=4, carNum=1003, brand=本田霸道, guidePrice=30.0, produceTime=2000-10-11, carType=燃油车)], prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=3, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]} Car(id=1, carNum=1001, brand=宝马520Li, guidePrice=10.0, produceTime=2022-09-01, carType=燃油车) Car(id=2, carNum=1002, brand=奔驰E300E, guidePrice=55.0, produceTime=2022-11-11, carType=新能源) Car(id=4, carNum=1003, brand=本田霸道, guidePrice=30.0, produceTime=2000-10-11, carType=燃油车)