Mybatis - 基础知识
Mybatis框架 - 半自动的对象关系映射ORM框架
- 资源管理
- 封装样板代码
- 实现对象关系映射(参数处理和结果集处理)
- SQL语句与业务代码解耦,通过xml配置实现sql的统一管理
- 动态SQL
- 缓存机制和插件机制
Mybatis使用案例:
public static void mapperTest(){
// 核心对象1: SqlSessionFactoryBuilder:用于读取配置文件并构建出SqlSessionFactory
// 核心对象2: SqlSessionFactory:用于创建sqlSession的工厂对象,单例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
// 核心对象3: SqlSession:会话,用于一次sql请求,是线程不安全的。
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
// 核心对象4:mapper代理对象:作用 - 采集调用方法名和参数,映射成mybatis中的statementId和params,在invocationHanlder.invoke()方法中实现sql的调用
KiqiMapper kiqiMapper = sqlSession.getMapper(KiqiMapper.class);
Kiqi kiqi = new Kiqi(1,"kiqi","123456",18,"kiqi$123");
kiqiMapper.insert(kiqi);
System.out.println(kiqi);
} catch (Exception e){
e.printStackTrace();
} finally {
sqlSession.close();
}
}
PS:对象关系映射ORM框架(Object Relational Mapping),用于解决对象与关系数据库元数据之间互不匹配的问题。
mybatis-config.xml
<!-- 在SqlSessionFactoryBuilder.build()方法中完成解析,解析后会构成Configuration对象,存在于SqlSessionFactory中 -->
<configuration>
<!-- 配置文件路径 通过${}符号引用其中的数据 -->
<properties resource="db.properties"/>
<!-- 核心配置 -->
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!-- 1. 开启全局缓存(二级缓存),默认 true -->
<!-- 一级缓存是基于session的,在同一个session中两次同样的select语句会触发缓存操作,而update类语句会则会清空缓存 -->
<!-- 二级缓存是基于namespace的,还需在具体的mapper.xml文件中配置缓存才能使对应的namespace应用缓存,与事务(cache是跨事务可见的)相关,只有事务提交后才会设置缓存 -->
<setting name="cacheEnabled" value="true"/>
<!-- 2. 延迟加载的全局开关,当开启时,所有关联对象都会延迟加载。默认 false. 1 + N关联查询,使后面的N在需要时(对应属性被使用)才执行 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 与lazyLoadingEnabled一同使用,aggressiveLazyLoading = true代表:对象在被调用任何方法时均触发延迟加载动作 -->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<!--<setting name="proxyFactory" value="CGLIB" />-->
<!--设置执行器类型,默认SIMPLE普通执行器,REUSE重用与处理语句,BATCH重用语句且批量执行-->
<setting name="defaultExecutorType" value="SIMPLE"/>
<!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
<!-- <setting name="localCacheScope" value="STATEMENT"/> -->
<setting name="localCacheScope" value="SESSION"/>
</settings>
<!-- 别名,用于简化一些全类名的拼写 - mybatis提供了很多预制的别名,如String -->
<typeAliases>
<typeAlias alias="kiqi" type="top.kiqi.mybatis.entity.Kiqi" />
</typeAliases>
<!-- 类型转换器,jdbc类型和java类型的相互映射转换,允许自定义,应用时在具体的statement语句或resultMap中设置 -->
<typeHandlers>
<typeHandler handler="top.kiqi.mybatis.handler.MyTypeHandler"></typeHandler>
</typeHandlers>
<!--四大插件: ①Executor(执行器) ②ParameterHandler(参数处理) ③ResultSetHandler(结果集处理) ④StatementHandler(语句执行) -->
<plugins>
<plugin interceptor="top.kiqi.mybatis.intercept.MyPageInterceptor">
<property name="kiqi" value="123456" />
</plugin>
<plugin interceptor="top.kiqi.mybatis.intercept.SQLInterceptor">
</plugin>
</plugins>
<!-- 配置环境 一个environment代表一个数据库 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!-- 事务配置 - 在Spring中,该项配置会被Spring覆盖 -->
<dataSource type="POOLED">
<property name="driver" value="${dataSource.driver}"/>
<property name="url" value="${dataSource.url}"/>
<property name="username" value="${dataSource.username}"/>
<property name="password" value="${dataSource.password}"/>
</dataSource>
</environment>
</environments>
<!-- Mapper.xml 映射文件配置 -->
<mappers>
<mapper resource="mapping/KiqiMapper.xml"/>
<!--<mapper package="top.kiqi.mybatis.dao"/>-->
<!--<mapper class="top.kiqi.mybatis.dao.KiqiMapper"/>-->
</mappers>
</configuration>
mapper.xml
<mapper namespace="top.kiqi.mybatis.dao.KiqiMapper">
<!-- 1, 只有当namespace中存在cache标签,该namespace才使用二级缓存-->
<cache type="org.apache.ibatis.cache.impl.PerpetualCache" size="1024" eviction="LRU" flushInterval="120000" readOnly="false"/>
<!-- 2. 重用语句块 -->
<sql id="Base_Column_List">
id, username, password, age, addr
</sql>
<!-- 3. 结果集,用于结果集映射到java对象-->
<resultMap id="BaseResultMap" type="top.kiqi.mybatis.entity.Kiqi">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="username" jdbcType="VARCHAR" property="username" />
<result column="password" jdbcType="VARCHAR" property="password" />
<result column="age" jdbcType="INTEGER" property="age" />
<result column="addr" jdbcType="VARCHAR" property="addr" />
</resultMap>
<!-- 4. 增删改查标签 -->
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from kiqi
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
delete from kiqi
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" useGeneratedKeys="true" parameterType="top.kiqi.mybatis.entity.Kiqi">
insert into kiqi (username, password,
age, addr)
values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
#{age,jdbcType=INTEGER}, #{addr,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="top.kiqi.mybatis.entity.Kiqi">
insert into kiqi
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="username != null">
username,
</if>
<if test="password != null">
password,
</if>
<if test="age != null">
age,
</if>
<if test="addr != null">
addr,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="username != null">
#{username,jdbcType=VARCHAR},
</if>
<if test="password != null">
#{password,jdbcType=VARCHAR},
</if>
<if test="age != null">
#{age,jdbcType=INTEGER},
</if>
<if test="addr != null">
#{addr,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="top.kiqi.mybatis.entity.Kiqi">
update kiqi
<set>
<if test="username != null">
username = #{username,jdbcType=VARCHAR},
</if>
<if test="password != null">
password = #{password,jdbcType=VARCHAR},
</if>
<if test="age != null">
age = #{age,jdbcType=INTEGER},
</if>
<if test="addr != null">
addr = #{addr,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="top.kiqi.mybatis.entity.Kiqi">
update kiqi
set username = #{username,jdbcType=VARCHAR},
password = #{password,jdbcType=VARCHAR},
age = #{age,jdbcType=INTEGER},
addr = #{addr,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>
tips
-
逻辑翻页和物理翻页:
- 逻辑翻页(将数据全部查询到java中,再根据offset丢弃范围之外的数据) - Mybatis RowBounds对象
- 物理翻页(Sql中采用limit字段实现定向查询) - PageHelper插件,通过拦截StatmentHandler完成SQL语句修改,实现物理翻页
-
#{}和${}
#{}
代表预编译,参数部分用?代替,可以防止注入(可缓存,性能高),而${}只是简单的字符串替换,并不能防止sql注入 -> 在能使用#{}的地方均使用#{}
-
实现模糊查询:
① 字符串拼接:Like %${name}%
--- 存在注入风险
② CONCAT表达式:Like CONCAT('%',#{name})
-
批量更新
① foreach动态sql语句
② BatchExecutor
欢迎疑问、期待评论、感谢指点 -- kiqi,愿同您为友
-- 星河有灿灿,愿与之辉