MyBatis进阶
内容纲要
MyBatis日志管理
- 日志文件是用于记录系统操作事件的记录文件或文件集合
- 日志保存历史数据,是诊断问题以及理解系统活动的重要依据
SLF4j与Logback
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%thread] %d{HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!--
日志输出级别(优先级高到低):
error: 错误 - 系统的故障日志
warn: 警告 - 存在风险或使用不当的日志
info: 一般性消息
debug: 程序内部用于调试信息
trace: 程序运行的跟踪信息
-->
<root level="debug">
<appender-ref ref="console"/>
</root>
</configuration>
动态SQL
- 动态SQL是指根据参数数据动态组织SQL的技术
MyBatis二级缓存
- 一级缓存默认开启,缓存范围SqlSession会话
- 二级缓存手动开启,属于范围Mapper Namespace
缓存的范围
二级缓存运行规则
- 二级开启后默认所有查询操作均使用缓存
- 写操作commit提交时对该namespace缓存强制清空
- 配置useCache=false可以不用缓存
- 配置flushCache=true代表强制清空缓存
<!--开启了二级缓存
eviction是缓存的清除策略,当缓存对象数量达到上限后,自动触发对应算法对缓存对象清除
1.LRU – 最近最少使用的:移除最长时间不被使用的对象。
O1 O2 O3 O4 .. O512
14 99 83 1 893
2.FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
3.SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
4.WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval 代表间隔多长时间自动清空缓存,单位毫秒,600000毫秒 = 10分钟
size 缓存存储上限,用于保存对象或集合(1个集合算1个对象)的数量上限
readOnly 设置为true ,代表返回只读缓存,每次从缓存取出的是缓存对象本身.这种执行效率较高
设置为false , 代表每次取出的是缓存对象的"副本",每一次取出的对象都是不同的,这种安全性较高
-->
<cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/>
<!-- useCache="false"代表不使用缓存 **全局查询** -->
<!--flushCache="true"在sql执行后强制清空缓存 **写添加**,清空的同时,查询出来的结果不会方法缓存中-->
MyBatis多表级联查询
1到多
实体类对象1的一方关联上多的一方
多的一方采用List类型
<!--
resultMap可用于说明一对多或者多对一的映射逻辑
id 是resultMap属性引用的标志
type 指向One的实体(Goods)
-->
<resultMap id="rmGoods1" type="com.imooc.mybatis.entity.Goods">
<!-- 映射goods对象的主键到goods_id字段 -->
<id column="goods_id" property="goodsId"></id>
<!--
collection的含义是,在
select * from t_goods limit 0,1 得到结果后,对所有Goods对象遍历得到goods_id字段值,
并代入到goodsDetail命名空间的findByGoodsId的SQL中执行查询,
将得到的"商品详情"集合赋值给goodsDetails List对象.
-->
<collection property="goodsDetails" select="goodsDetail.selectByGoodsId"
column="goods_id"/>
</resultMap>
<select id="selectOneToMany" resultMap="rmGoods1">
select * from t_goods limit 0,10
</select>
============================
<select id="selectByGoodsId" parameterType="Integer"
resultType="com.imooc.mybatis.entity.GoodsDetail">
select * from t_goods_detail where goods_id = #{value}
</select>
多到1
实体类对象多的一方关联上1的一方
<resultMap id="rmGoodsDetail" type="com.imooc.mybatis.entity.GoodsDetail">
<id column="gd_id" property="gdId"/>
<result column="goods_id" property="goodsId"/>
<association property="goods" select="goods.selectById" column="goods_id"></association>
</resultMap>
<select id="selectManyToOne" resultMap="rmGoodsDetail">
select * from t_goods_detail limit 0,20
</select>
分页插件PageHelper
- 当前页数据查询 - select * form tab limit 0,10
- 总记录数查询 - select count(*) from tab
- 程序计算总页数、上一页页码、下一页页码
public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*获取页面传过来的当前页码*/
String pageNum = request.getParameter("pageNum");
/*如果第一次查询时没有分页页面,默认是第一页*/
if(pageNum==null) pageNum="1";
/* 设置起始查询页码,以及每页条数*/
PageHelper.startPage(Integer.parseInt(pageNum),20);
/* 查询蛋糕*/
List<Cake> list = cakeBiz.getAll();
/*把查询的结果封装到PageInfo中*/
PageInfo pageInfo = PageInfo.of(list);
/* 把pageInfo放到域中并转发到蛋糕列表页中*/
request.setAttribute("pageInfo",pageInfo);
request.getRequestDispatcher("/WEB-INF/pages/admin/cake_list.jsp").forward(request,response);
}
<div class="col-xs-12 col-md-9 text-right">
<%--list8--%>
<form action="/admin/Cake/list.do" method="post">
共${pageInfo.total}条 ${pageInfo.pageNum}/${pageInfo.pages}
<div class="btn-group">
<button type="submit" name="pageNum" value="${pageInfo.pageNum-1}"
class="btn btn-default light">
<i class="fa fa-chevron-left"></i>
</button>
<button type="submit" name="pageNum" value="${pageInfo.pageNum+1}"
class="btn btn-default light">
<i class="fa fa-chevron-right"></i>
</button>
</div>
</form>
</div>
PageHelper使用流程
- maven引入PageHelper与jspparser
- mybatis-config.xml增加Plugin配置
- 代码中使用PageHelper.startPager()自动分页
<dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>5.1.10</version> </dependency> <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>2.0</version> </dependency> ================================= <!--启用Pagehelper分页插件--> <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> <!--设置数据库类型--> <property name="helperDialect" value="mysql"/> <!--分页合理化--> <property name="reasonable" value="true"/> </plugin> </plugins> ======spring+mybatis+pagerhelper整合=========== <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--数据源,关联申请的数据源--> <property name="dataSource" ref="dataSoure"/> <!--配置别名--> <property name="typeAliasesPackage" value="oes.entity"/> <!--配置pageHelper--> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageHelper"> <property name="properties"> <value> <!--数据源类型:mysql, mariadb, sqlite, oracle, hsqldb, postgresql, sqlserver, db2, informix, h2, sqlserver2012--> helperDialect=mysql <!--分页合理化参数,设置为true时,pageNum<=0时会查询第一页,pageNum>pages(超过总数时),会查询最后一页。--> reasonable=true </value> </property> </bean> </array> </property> </bean>
不同数据库分页的实现原理
- MySQL分页
select * form table limit 10,20
第一个参数:起始行号
第二个参数:从第一个参数往后去多少行 - Oracle
select t3.* from (
select t2.*, rownum as row num from (
select * from table order by id asc
) t2 where rownum< = 20
) t3
where t2.row num> 1 1
- SQL Server 2000
select top 3 * from table
where
id not in.
(select top 15 id from table)
- SQL Server 2012+
select * from table order by id
offset 4 rows fetch next 5 rows only
MyBatis整合C3P0连接池
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
=====创建一个C3P0DataSourceFactory类==========
/**
* C3P0与MyBatis兼容使用的数据源工厂类
*/
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {
public C3P0DataSourceFactory(){
this.dataSource = new ComboPooledDataSource();
}
}
=================config==================
<environment id="dev">
<!-- 采用JDBC方式对数据库事务进行commit/rollback -->
<transactionManager type="JDBC"></transactionManager>
<!--采用连接池方式管理数据库连接-->
<!--<dataSource type="POOLED">-->
<dataSource type="com.imooc.mybatis.datasource.C3P0DataSourceFactory">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://47.114.2.235:3306/jdbc?useUnicode=true&characterEncoding=UTF-8"/>
<property name="user" value="jdbc"/>
<property name="password" value="jdbc"/>
<property name="initialPoolSize" value="5"/>
<property name="maxPoolSize" value="20"/>
<property name="minPoolSize" value="5"/>
<!--...-->
</dataSource>
</environment>
MyBatis批量处理
- 批量插入
<!--INSERT INTO table-->
<!--VALUES ("a" , "a1" , "a2"),("b" , "b1" , "b2"),(....)-->
<insert id="batchInsert" parameterType="java.util.List">
INSERT INTO t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id)
VALUES
<foreach collection="list" item="item" index="index" separator=",">
(#{item.title},#{item.subTitle}, #{item.originalCost}, #{item.currentPrice}, #{item.discount}, #{item.isFreeDelivery}, #{item.categoryId})
</foreach>
</insert>
- 批量删除
<!--in (1901,1902)-->
<delete id="batchDelete" parameterType="java.util.List">
DELETE FROM t_goods WHERE goods_id in
<foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
MyBatis注解开发
public interface GoodsDAO {
@Select("select * from t_goods where current_price between #{min} and #{max} order by current_price limit 0,#{limt}")
public List<Goods> selectByPriceRange(@Param("min") Float min ,@Param("max") Float max ,@Param("limt") Integer limt);
@Insert("INSERT INTO t_goods(title, sub_title, original_cost, current_price, discount, is_free_delivery, category_id) VALUES (#{title} , #{subTitle} , #{originalCost}, #{currentPrice}, #{discount}, #{isFreeDelivery}, #{categoryId})")
//<selectKey>
@SelectKey(statement = "select last_insert_id()" , before = false , keyProperty = "goodsId" , resultType = Integer.class)
public int insert(Goods goods);
@Select("select * from t_goods")
//<resultMap>
@Results({
//<id>
@Result(column = "goods_id" ,property = "goodsId" , id = true) ,
//<result>
@Result(column = "title" ,property = "title"),
@Result(column = "current_price" ,property = "currentPrice")
})
public List<GoodsDTO> selectAll();
}
共有 0 条评论