mybatis—— OGNL表达式
(mapper xml文件内if标签内)
OGNL 全称 Object-Graph Navigation Language,是 Java 中的一个开源的表达式语言,用于访问对象数据。也是mybatis实现动态sql的基础。
常见的OGNL表达式
表达式 | 说明 | 表达式 | 说明 |
---|---|---|---|
A or B | 或关系 | A and B | 与关系 |
A == B; A eq B | 相等 | A != B; A neq B | 不等 |
A lt B; A < B | 小于 | A gt B; A > B | 大于 |
A lte B; A <= B | 小于等于 | A gte B; A >= B | 大于等于 |
!A 或者 not A | 非,取反 | A.method(args) | 调用对象方法 |
A.property | 访问属性值 | A[k] | 访问数组、链表(k为序号)或者 Map(k为键值) |
2.2 #{}与${}的区别
${}与#{}都是从参数列表中取值
#{}
是编译好SQL语句再取值,是经过预编译的,是安全的。
#{}
引用参数的时候,Mybatis会把这个参数认为是一个字符串,并自动加上单引号''
示例:
SELECT * FROM p1_staff_info WHERE id = #{id}
执行时会转换为
SELECT * FROM p1_staff_info WHERE id = 'p0051 or 1 = 1'
${}是取值以后再去编译SQL语句;
${}是未经过预编译的,仅仅是取变量的值,是不安全的,存在SQL注入风险;
示例:
SELECT * FROM stu_info WHERE id = ${id}
假如传入的参数id = "'p0051' or 1 = 1";
则执行时会转换为
SELECT * FROM p1_staff_info WHERE id = 'p0051' or 1 = 1;
3 映射文件mapper.XML语法
3.1 映射关系resultMap
<!--orm 对象和数据表之间的映射关系-->
<resultMap id="baseMap" type="com.st.pojo.User">
<result column="id" property="id" jdbcType="INTEGER"/>
<result column="u_name" property="name" jdbcType="VARCHAR"/>
<result column="time" property="createTime" jdbcType="TIMESTAMP"/>
<result column="u_money" property="money" jdbcType="DECIMAL"/>
</resultMap>
column:数据表字段名
property:pojo类属性名
jdbcType:数据类型
3.2 查询select
parameterType:接收参数的数据类型
resultMap:查询数据库返回结果的映射关系,关联baseMap的id属性
resultType:查询数据返回结果的数据类型,如:java.lang.String
<select id="queryUser" parameterType="_User" resultMap="baseMap">
SELECT * FROM p2_user
<where>
<if test="name != null">AND u_name = #{name}</if>
<if test="phone != null">AND u_phone = #{phone}</if>
<if test="pass != null">AND u_pass = #{pass}</if>
</where>
</select>
2.3 添加insert
insert语句默认返回值是int类型,表示insert执行成功几条记录
<!--
添加用户,并返回用户主键,
useGeneratedKeys 设置是否使用JDBC的getGenereatedKeys方法获取主键并赋值到keyProperty设置属性中
keyProperty 实体类主键属性
需要sqlsession开始事务自动提交openSession(true);
-->
<insert id="add" parameterType="_User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO p2_user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">u_name,</if>
<if test="pass != null">u_pass,</if>
<if test="phone != null">u_phone,</if>
</trim>
<trim prefix="VALUES(" suffix=")" suffixOverrides=",">
<if test="name != null">#{name},</if>
<if test="pass != null">#{pass},</if>
<if test="phone != null">#{phone},</if>
</trim>
</insert>
3.4 批量插入
<insert id="addAll" parameterType="java.util.List">
<!--
使用批量插入需要在jdbc:url中添加allowMultiQueries=true
作用:
1.可以在sql语句后携带分号,实现多语句执行。
2.可以执行批处理,同时发出多个SQL语句。
collection 被遍历的结果集
item 本次遍历获取的元素
index 当前迭代的次数
separator:每次一遍历之后,语句末尾拼接指定字符
-->
<foreach collection="list" item="sf" index="index" separator=";">
INSERT INTO p1_staff_info
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="sf.id != null">id,</if>
<if test="sf.name != null">s_name,</if>
</trim>
<trim prefix="VALUES(" suffix=")" suffixOverrides=",">
<if test="sf.id != null">#{sf.id, jdbcType=INTEGER},</if>
<if test="sf.name != null">#{sf.name, jdbcType=VARCHAR},</if>
</trim>
</foreach>
</insert>
3.5 更新update
<update id="update" parameterType="_User">
UPDATE p2_user
<set>
<if test="name != null">u_name = #{name, jdbcType=VARCHAR},</if>
<if test="pass != null">u_pass = #{pass, jdbcType=VARCHAR},</if>
<if test="phone != null">u_phone = #{phone, jdbcType=VARCHAR},</if>
</set>
<where>
<if test="id != null">and id = #{id, jdbcType=INTEGER}</if>
</where>
</update>
3.6 封装sql
<!-- 封装sql语句 -->
<sql id="cs">id,s_name,s_sex </sql>
<!-- include标签引入封装的sql语句,refid关联一个sql标签的id属性-->
select <include refid="cs"/> from student
4 settings
设置名 | 描述 | 可选值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局地开启或关闭所有 mapper 中的缓存(二级缓存) | true,false | false |
lazyLoadingEnabled | 延迟加载的全局开关,当开启时,所有关联对象都会延迟加载 | true,false | false |
defaultStatementTimeout | 设置数据库查询超时时间 | 任意正整数 | null |
mapUnderscoreToCamelCase | 是否开启自动驼峰命名规则(camel case)映射 | true,false | false |
localCacheScope | MyBatis会默认缓存会话中的查询,即 SESSION,若无需缓存则设置为 STATEMENT | SESSION,STATEMENT | SESSION |
logPrefix | 指定 MyBatis 日志名称前缀 | 任何字符串 | 未设置 |
logImpl | 指定 MyBatis 日志的实现类,未指定时将自动查找 | SLF4J,LOG4J,LOG4J2,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING | 未设置 |
proxyFactory | 指定创建具有延迟加载能力的对象所用到的代理工具 | CGLIB,JAVASSIST | JAVASSIST |
eg:
<settings>
<!--日志打印sql语句-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!-- 开启下划线转驼峰的配置 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
4.2 typeAliases
<typeAliases>
<typeAlias type="com.model.User" alias="User"/>
</typeAliases>
或
<typeAliases>
<!-- 扫描该包下所有类,每个类的别名是其类名首字母小写,如 User类的别名为 user -->
<package name="com.model"/>
</typeAliases>
4.3 事务管理器transactionManager
在 xml 文件中对应
JDBC:直接使用了 JDBC 的提交和回滚机制。
MANAGED:让容器来管理事务的整个生命周期,例如 spring 容器。
5 加载配置文件,创建SqlSession对象
//加载mybatis.xml文件
InputStream in = Resources.getResourceAsStream("mybatis.xml");
//创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//使用工厂生产SqlSession对象
SqlSession sqlSession = factory.openSession();
//使用SqlSession创建Mapper接口的代理对象
StuDao stuDao = sqlSession.getMapper(StuDao.class);
6常用注解
@Param
参数标签,在Mapper的方法签名上标注参数,为SQL语句中参数赋值而服务,指定参数名称
public int delete(@Param("id") Integer id);
7 缓存
缓存的作用
在参数和SQL完全一样的情况下,多次调用mapper方法,只会执行一次SQL,第一次执行sql查询到的结果集会被保存在缓存中,后面重复调用mapper方法返回的是缓存中的结果集;
缓存的目的
提高对数据库查询的效率,提高应用程序的性能;
一级缓存
Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。
所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL。
因为使用SelSession第一次查询后,MyBatis会将查询出来的结果集放在缓存中,以后再查询的时候,如果没有声明需要刷新缓存,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
特征:
1 一级缓存是默认开启的;
2 一级缓存只是相对于同一个SqlSession而言;
3 在一个会话中,调用 insert、update、delete 语句时,会话中的缓存会被刷新;
关闭一级缓存
通过 flushCache 属性来关闭 select 查询的一级缓存
<select id="" flushCache="true">
二级缓存
MyBatis的二级缓存是Application(应用程序)级别的缓存,二级缓存默认是不开启的,二级缓存的有效范围为一个 SqlSessionFactory 生命周期,绝大多数情况下,应用都会只有一个 SqlSessionFactory,因此我们可以把二级缓存理解为全局缓存。
二级缓存的开启需要进行配置,实现二级缓存的时候,MyBatis要求返回的POJO(简单java类)必须是可序列化的,也就是要求实现Serializable接口。
特征:
1 二级缓存默认是关闭的;
2 二级缓存是Application(应用程序)级别的缓存;
3 二级缓存要求返回的POJO(简单java类)必须是可序列化的;
开启二级缓存
mybtis.xml配置文件中开启二级缓存
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
<!--开启本mapper的namespace下的二级缓存-->
<!--
eviction:代表的是缓存回收策略,目前MyBatis提供以下策略。
(1) LRU,最近最少使用的,即最长时间不用的对象
(2) FIFO,先进先出,按对象进入缓存的顺序来移除他们
(3) SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象
(4) WEAK,弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象。这里采用的是LRU,移除最长时间不用的对象
flushInterval:刷新间隔时间,单位为毫秒,这里配置的是60秒刷新,如果你不配置它,那么当新SQL被执行的时候才会去刷新缓存。
size:引用数目,一个正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。最大缓存1024个对象
readOnly:只读,意味着缓存数据只能读取而不能修改,这样设置的好处是我们可以快速读取缓存,缺点是我们没有办法修改缓存,他的默认值是true,不允许我们修改
-->
<cache eviction="LRU" flushInterval="60000" size="1024" readOnly="true"/>
<!--可以通过设置useCache来规定这个sql是否开启二级缓存,
ture是开启,false是关闭-->
<select id="selectAllStudents" resultMap="studentMap" useCache="true">
SELECT id, name, age FROM student
</select>
标签:事务管理,缓存,15,14,SqlSession,二级缓存,SQL,id,name
From: https://www.cnblogs.com/xiaoto9426/p/16967114.html