Java框架(二)--MyBatis进阶

MyBatis日志管理

什么是日志

日志文件是用于记录系统操作事件的记录文本或文件集合。
日志保存历史数据,是诊断问题以及理解系统活动的重要依据。

SLF4j与Logback

Java框架(二)--MyBatis进阶_第1张图片
logback和log4j是同一个人开发的,logback是log4j的升级版,从维护性和执行效率上都得到了提升。
在pom.xml中添加logback依赖:

<dependency>
  <groupId>ch.qos.logbackgroupId>
  <artifactId>logback-classicartifactId>
  <version>1.2.11version>
dependency>

在resources目录下新增logback.xml配置文件:


<configuration>
	
	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
		
		<encoder>
			
			<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
		encoder>
	appender>
	
	<root level="debug">
		<appender-ref ref="console"/>
	root>
configuration>

其他详细信息可以参考logback官网
https://logback.qos.ch/

MyBatis动态SQL

动态SQl

动态SQL是指根据参数数据动态组织SQL的技术。
Java框架(二)--MyBatis进阶_第2张图片
where标签会动态判断去掉第一个子语句的and。

MyBatis二级缓存

一级缓存默认开启,缓存范围SqlSession会话。
二级缓存手动开启,属于范围Mapper Namespace。

缓存的范围Java框架(二)--MyBatis进阶_第3张图片

二级缓存运行规则

二级缓存开启后默认所有查询操作均使用缓存。
写操作commit提交时对该namespace缓存强制清空。
配置useCache=false可以不用缓存。
配置flushCache=true代表强制清空缓存。

二级缓存配置

在相关mapper.xml文件中开启并配置二级缓存:

<mapper namespace="goods">
	
	<cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/>
	
	<select id="selectAll" useCache="false" ...>
		select ...
	select>
	
	<insert id="insert" flushCache="true" ...>
		insert ...
	insert>
mapper>

MyBatis多表级联查询

OneToMany对象关联查询

首先在主实体类中添加关联集合:

public class Goods{
	private Integer goodsId;
	private String title;
	private List<GooodsDetail> goodsDetails;
	...
}

然后在对应的mapper.xml文件中添加级联查询:


<resultMap id="rmGoods1" type="com.ql.mybatis.entity.Goods">
	
	<id column="goods_id" property="goodsId">id>
	
	<collection property="goodsDetails" select="goodsDetail.selectByGoodsId" column="goods_id"/>
resultMap>
<select id="selectOneToMany" resultMap="rmGoods1">
	select * from t_goods limit 0,1
select>

ManyToOne对象关联查询

首先在多的一方实体类中添加关联集合:

public class GoodsDetail{
	private Integer gdId;
	private Integer goodsId;
	private Goods goods;
	...
}

然后在对应的mapper.xml文件中添加级联查询:

<resultMap id="rmGoodsDetail" type="com...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_good_detail
select>

分页插件PageHelper

分页查询的麻烦事

当前页数据查询 - select * from tab limit 0,10
总记录数查询 - select count(*) from tab
程序计算总页数、上一页页码、下一页页码。
PageHelper官网:
https://pagehelper.github.io/

PageHelper使用流程

maven引入PageHelper与jsqlparser

<dependency>
  <groupId>com.github.pagehelpergroupId>
  <artifactId>pagehelperartifactId>
  <version>5.1.10version>
dependency>
<dependency>
  <groupId>com.github.jsqlparsergroupId>
  <artifactId>jsqlparserartifactId>
  <version>2.0version>
dependency>

mybatis-config.xml增加Plugin配置

<configuration>
	
	<plugins>
		<plugin interceptor="com.github.pagehelper.PageInterceptor">
			
			<property name="helperDialect" value="mysql"/>
			
			<property name="reasonable" value="true"/>
		plugin>
	plugins>
configuration>

代码中使用PageHelper.startPage()自动分页

/*startPage(pageNum, paseSize)方法会自动将下一次查询进行分页*/
PageHelper.startPage(2,10);
Page<Goods> page = (Page)session.selectList("goods.selectPage");
//selectPage的sql语句就是普通的select语句
page.getPages();//总页数
page.getTotal();//总记录数
page.getStartRow();//开始行号
page.getEndRow();//结束行号
page.getPageNum();//当前页码
List<Goods> data = page.getResult();//当前页数据

不同数据库分页的实现原理

MySQL分页
Java框架(二)--MyBatis进阶_第4张图片
Oracle
Java框架(二)--MyBatis进阶_第5张图片
SQL Server 2000
Java框架(二)--MyBatis进阶_第6张图片
SQL Sever 2012+
Java框架(二)--MyBatis进阶_第7张图片

MyBatis配置C3P0连接池

首先在pom.xml中引入依赖:

<dependency>
  <groupId>com.mchangegroupId>
  <artifactId>c3p0artifactId>
  <version>0.9.5.5version>
dependency>

创建C3P0DataSourceFactory(可以在项目目录下创建datasource包,在创建此类)

/*
C3P0与MyBatis兼容使用的数据源工厂类
*/
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory{
	public C3P0DataSourceFactory(){
		this.dataSource = new ComboPooledDataSource();
	}
}

mybatis-config.xml中配置数据源

      <dataSource type="com.ql.mybatis.datasource.C3P0DataSourceFactory">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/databaseName?useUnicode=true&characterEncoding=UTF-8"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
        <property name="initialPoolSize" value="5"/>
        <property name="maxPoolSize" value="20"/>
        <property name="minPoolSize" value="5"/>
      dataSource>

MyBatis批处理

批量新增

在相应的Mapper.xml中编写SQL


<insert id="batchInsert" parameterType="java.util.List">
	insert into t_goods (title, sub_title, original_cost ... )
	values 
	<foreach collection="list" item="item" index="index" separator=",">
		(#{item.title},#{item.subTitle}...)
	foreach>
insert>

在Java中调用时传List即可

session.insert("goods.batchInsert", list);

批量插入数据的局限
1、无法获得插入数据的id
2、批量生成的SQL太长,可能会被服务器拒绝。需要插入的数据太多时可以分批次插入。

批量删除

<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>
session.delete("goods.batchDelete", list);

MyBatis注解开发

Java框架(二)--MyBatis进阶_第8张图片
在dao包里创建GoodsDAO接口

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,...) values (#{title},#{subTitle},...)")
	//
	@SelectKey(statement="select last_insert_id()", before=false, keyProperty="goodsId", resultType=Integer.class)
	public int insert(Goods goods);

	@Select("select * from t_goods")
	//
	@Results({
		//
		@Result(column="goods_id", property="goodsId", id=true),
		@Result(column="title", property="title"),
		@Result(column="current_price", property="currentPrice")
	})
	public List<GoodsDTO> selectAll();
}

在mybatis-config.xml配置文件中增加相应的说明:

<mappers>
	
	<package name="com.ql.mybatis.dao"/>
mappers>

最后在Java代码中调用

//采用注解方式开发时先获取映射器,它会基于代理模式自动生成对应的实现类
GoodsDAO goodsDAO = session.getMapper(GoodsDAO.class);
List<Goods> list = goodsDAO.selectByPriceRange(100f,500f,20);
//insert()方法返回值代表本次成功插入的记录总数
int num = goodsDAO.insert(goods);
session.commit();//提交事务数据
List<GoodsDTO> list2 = goodsDAO.selectAll();

xml和注解开发区别

利用xml有更好的维护性,可以让我们在xml中对sql灵活的修改,更适合大型团队协作的项目。
利用注解有更好的程序编码的体验,不需要添加xml文件,在程序中直接修改即可,更适合小型敏捷开发的工程。

你可能感兴趣的:(Java工程师,java,缓存,MyBatis)