mybatis相关知识点
2017-07-23 16:14
330 查看
映射文件的相关属性
namespace命名空间
作用: 对sql进行分类化管理,理解sql隔离注意:使用mapper代理方法开发,namespace有特殊重要的作用
<!-- 需求:通过id查询用户表的记录 --> <select id="findUserById" parameterType="int" resultType="com.chaychan.mybatis.po.User"> SELECT * FROM USER WHERE id=#{value} </select>
上面代码的解释
id:标识映射文件中的 sql,将sql语句封装到mappedStatement对象中,所以将id称为statement的idparameterType:指定输入 参数的类型,这里指定int型
resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。
“#{}” 表示一个占位符号
“#{id}” 其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称.
${}的使用
<!-- 通过用户的名称模糊搜索用户,搜索的结果可能有多条 resultType指定就是单条记录所映射的java对象 ${}表示拼接sql串,将接收到的内容不加任何修饰拼接在sql中 使用${}拼接sql,会引起sql注入,比如传入的字符串是sql指令(有一定的风险) ${value}:接收输入的内容,如果传入的类型是简单类型,${}中只能用value --> <select id="findUserByName" parameterType="java.lang.String" resultType="com.chaychan.mybatis.po.User"> SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'; </select>
以上的模糊搜索会引起sql注入,所以还是使用下面的代码
<select id="findUserByName" parameterType="java.lang.String" resultType="com.chaychan.mybatis.po.User"> <!-- SELECT * FROM USER WHERE USERNAME LIKE '%${value}%'; 为了防止sql注入,所以采用下面的方式--> SELECT * FROM USER WHERE USERNAME LIKE #{value}; </select>
代码中传入参数替代占位符
List<User> list = sqlSession.selectList("test.findUserByName","%小明%");
插入数据
<!-- 添加用户 parameterType:指定输入参数的类型为pojo(包含用户信息) #{}指定pojo的属性名,就可以接收到相应的属性值,mybatis是通过OGNL获取属性值 --> <insert id="insertUser" parameterType="com.chaychan.mybatis.po.User"> insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}) </insert>
插入数据后拿到自增长的主键的值
<insert id="insertUser" parameterType="com.chaychan.mybatis.po.User"> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> SELECT LAST_INSERT_ID() </selectKey> insert into user(username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address}) </insert>
以上代码的解释
SELECT LAST_INSERT_ID(): 得到刚 insert进去记录的主键值,只适用于自增长主键keyProperty: 将查询到的主键值设置到parameterType对应的对象的哪个属性中,上述代码是将主键值设置到User对象的id属性中
order: SELECT LAST_INSERT_ID()的执行顺序,相对于insert来说的顺序
resultType: 指定SELECT LAST_INSERT_ID()的结果类型
在插入数据之前通过mysql的uuid()生成主键,然后再将其作为主键值插入
使用mysql的uuid()生成主键执行过程:
首先通过uuid()得到主键,将主键设置到user对象的id属性中
其次在insert执行时,从user对象中取出id属性值
<insert id="insertUser" parameterType="com.chaychan.mybatis.po.User"> <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"> SELECT uuid() </selectKey> insert into user(id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address}) </insert>
mapper的编写
程序员编写mapper接口需要遵循一些开发规范,mybatis可以自动生成mapper接口实现类的代理对象开发规范:
1.在mapper.xml中的namespace等于mapper接口的类的全路径
<mapper namespace="com.chaychan.mybatis.mapper.UserMapper">
2.mapper.java接口中的方法名要和mapper.xml中statement的id一致
3.mapper.java接口中的方法的输入参数类型要和mapper.xml中statement的parameterType指定的类型一致
4.mapper.java接口中的方法返回值类型要和mapper.xml中statement的resultType指定的类型一致
如mapper.xml中代码:
<select id="findUserById" parameterType="int" resultType="com.chaychan.mybatis.po.User"> SELECT * FROM USER WHERE id=#{value} </select>
mapper接口中的方法:
/**根据id查找用户信息*/ public User findUserById(int id) throws Exception;
定义别名
单个别名的定义SqlMapConfig.xml中配置User对象全路径对应的别名为user
<!-- 定义别名 --> <typeAliases> <!--单个别名的定义--> <typeAlias type="com.chaychan.mybatis.po.User" alias="user"/> </typeAliases>
mapper.xml中只需使用别名user:
<select id="findUserById" parameterType="int" resultType="user"> SELECT * FROM USER WHERE id=#{value} </select>
批量别名的定义
SqlMapConfig.xml中配置要包名
<!-- 定义别名 --> <typeAliases> <!-- 批量别名的定义 指定包名,mybatis就会自动扫描包中的po类,自动定义别名,别名为类名(首字母大小写都可以) --> <package name="com.chaychan.mybatis.po"/> </typeAliases>
加载映射文件
单个加载映射文件,通过mapper接口加载映射文件
批量加载映射文件,指定mapper接口所在的包名,mybatis会自动加载mapper接口
两种方法都要遵循一定的规范:需要将mapper接口的类名和mapper.xml映射文件名保持一致,且放在同一个目录下
<!-- 加载 映射文件 --> <mappers> <mapper resource="sqlmap/User.xml"/> <!-- <mapper resource="mapper/UserMapper.xml"/> --> <!-- 单个加载映射文件,通过mapper接口加载映射文件 遵循一定的规范:需要将mapper接口的类名和mapper.xml映射文件名保持一致,且放在同一个目录下 --> <!-- <mapper class="com.chaychan.mybatis.mapper.UserMapper"/> --> <!-- 批量加载映射文件 指定mapper接口所在的包名,mybatis会自动加载mapper接口 遵循一定的规范:需要将mapper接口的类名和mapper.xml映射文件名保持一致,且放在同一个目录下 --> <package name="com.chaychan.mybatis.mapper"/> </mappers>
reusltMap入门
<!-- 定义resultMap 将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系 type:resultMap最终映射的java对象类型,可以使用别名 id:对resultMap的唯一标识 --> <resultMap type="user" id="userResultMap"> <!-- id表示查询结果集中唯一标识 column:查询出来的列名 property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系 (对应关系) --> <id column="id_" property="id"/> <!-- result:对普通名映射定义 column:查询出来的列名 property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系 (对应关系) --> <result column="username_" property="username"/> </resultMap> <!-- 使用resultMap进行输出映射 resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace --> <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap"> SELECT id id_,username username_ FROM USER WHERE id=#{value} </select>
定义sql片段
<!-- 定义sql片段 id:sql片段的唯 一标识 经验:是基于单表来定义sql片段,这样话这个sql片段可重用性才高 在sql片段中不要包括 where --> <sql id="user_query_where"> <if test="userCustom != null"> <if test="userCustom.sex != null and userCustom.sex != ''"> and sex = #{userCustom.sex} </if> <if test="userCustom.username != null and userCustom.username != ''"> and username like '%${userCustom.username}%' </if> </if> </sql>
引用sql片段
<select id="findUserList" parameterType="userQueryVo" resultType="userCustom"> select * from user <where> <include refid="user_query_where" /> </where> </select>
foreach的使用
<if test="ids != null"> <!-- 使用 foreach遍历传入ids 使用实现下边的sql拼接: AND (id=1 OR id=10 OR id=16) --> <foreach collection="ids" item="item_id" open="AND (" close=")" separator="OR"> id=#{item_id} </foreach> <!-- 使用实现下边的sql拼接: AND id in(1,10,16) --> <foreach collection="ids" item="item_id" open="AND id in(" close=")" separator=","> #{item_id} </foreach> </if>
collection:指定输入对象中集合属性
item:每个遍历生成对象中
open:开始遍历时拼接的串
close:结束遍历时拼接的串
separator:遍历的两个对象中需要拼接的串
延迟加载
sqlConfig.xml中配置开启延迟加载<!-- 全局配置参数,需要时再设置 --> <settings> <!-- 打开延迟加载 的开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 将积极加载改为消极加载即按需要加载 --> <setting name="aggressiveLazyLoading" value="false"/> <!-- 开启二级缓存 --> <!-- <setting name="cacheEnabled" value="true"/> --> </settings>
定义一个延迟加载的mapper,如查询订单的时候,延迟加载用户信息,因为orders表中的user_id关联user表的id,当需要获取user对象的时候,就会执行延迟加载。
相当于两步:
1.先查询orders表获取到订单;
2.根据订单对象中user_id查找出相关的user对象
<!-- 延迟加载的resultMap --> <resultMap type="com.chaychan.mybatis.po.Orders" id="OrdersUserLazyLoadingResultMap"> <!--对订单信息进行映射配置 --> <id column="id" property="id" /> <result column="user_id" property="userId" /> <result column="number" property="number" /> <result column="createtime" property="createtime" /> <result column="note" property="note" /> <!-- 实现对用户信息进行延迟加载 select:指定延迟加载需要执行的statement的id(是根据user_id查询用户信息的statement) 要使用userMapper.xml中findUserById完成根据用户id(user_id)用户信息的查询,如果findUserById不在本mapper中需要前边加namespace column:订单信息中关联用户信息查询的列,是user_id 关联查询的sql理解为: SELECT orders.*, (SELECT username FROM USER WHERE orders.user_id = user.id)username, (SELECT sex FROM USER WHERE orders.user_id = user.id)sex FROM orders --> <association property="user" javaType="com.chaychan.mybatis.po.User" column="user_id" select="com.chaychan.mybatis.mapper.UserMapper.findUserById" ></association> </resultMap> <!-- 查询订单关联查询用户,用户信息需要延迟加载 --> <select id="findOrdersUserLazyLoading" resultMap="OrdersUserLazyLoadingResultMap"> SELECT * FROM orders </select>
测试代码
List<Orders> list = ordersMapperCustom.findOrdersUserLazyLoading(); for (Orders orders : list) { User user = orders.getUser(); System.out.println(user); }
当获取list的时候,控制台会输入查找orders表的sql语句,当orders对象调用getUser()方法的时候,控制台会输出根据id查找用户的sql语句。
查询缓存
一级缓存是sqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据,不同的sqlSession之间的缓存数据区域(HashMap)是互不影响的。二级缓存是mapper级别的缓存,多个sqlSession去操作同一个Mapper中的sql语句,多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。
为什么要用缓存?如果缓存中有数据,就不用到数据库中去查找,大大提高系统的性能。
一级缓存的原理
例子:第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户的信息,如果没有,从数据查询用户信息。得到用户信息后,存储在以及缓存中。
如果sqlSession去执行commit操作(执行插入、更新、删除),将清空sqlSession中的一级缓存,这样做的目的是为了让缓存中存储的是最新的信息,避免脏读。
第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户的信息,缓存中有,直接从缓存中获取用户信息。
二级缓存
mybatis默认开启一级缓存,如果要开启二级缓存,需要在xml中进行配置原理:
sqlSession1去查询用户id为1的用户信息,查询到用户信息后将数据存储到二级缓存中。
sqlSession2去查询用户id为1的用户信息时,先去缓存中查找,如果存在则直接取出数据。
二级缓存和一级缓存的区别,二级缓存的范围更大,多个sqlSession可以共享一个Mapper的二级缓存区域,不如UserMapper有自己的二级缓存区域,其他mapper也有对应的二级缓存区域,按namespace区分。即每一个namespace的mapper有一个二级缓存区域。
如果两个mapper的namespace相同,这两个mapper执行sql查询到的数据将存在相同的二级缓存区域中。
整合ehcache
配置mapper中cache中的type为ehcache对cache接口的实现类<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
导入mybatis-ehcache-1.0.2.jar,ehcache-core-2.6.5.jar
相关文章推荐
- Mybatis相关知识点
- mybatis事务相关知识点
- mybatis相关知识点的总结
- mybatis PageHelper和pageInfo的相关知识点
- 哈夫曼树相关知识点总结
- 布局相关的知识点
- JavaScript相关知识点
- 使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件(转)
- 【solr基础教程之一】Solr相关知识点串讲
- getchar()函数与scanf()函数相关知识点
- TCP/IP相关知识点与面试(2)
- 大数据实时计算相关知识点
- 微信小程序--后端管理平台业务4--Mybatis模糊查询相关
- Vue2.0相关的知识点
- UITableView相关知识点
- 使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件(转)
- 构造函数初始化列表相关知识点集合
- 使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件
- 使用Mybatis-Generator自动生成Dao、Model、Mapping相关文件
- IO相关,小知识点