ch.qos.logback logback-classic 1.2.3
2.resource下新增配置文件logback.xml:
%d{HH:mm:ss.sss} [%thread] %-5level %logger{256} -%msg%n
效果如下:
```
测试类:```java@Testpublic void testDynamicSQL() {SqlSession sqlSession = null;try {Map param = new HashMap();param.put("categoryId", 44);param.put("currentPrice", 500);sqlSession = MyBatisUtils.openSession();// 返回表示插入成功的记录条数List list = sqlSession.selectList("goods.dynamicSQL", param);for (Goods good : list) {System.out.println(good.toString());}} catch (Exception e) {if (sqlSession != null) {sqlSession.rollback();}e.printStackTrace();} finally {MyBatisUtils.closeSession(sqlSession);}}
一级缓存存放在当前sqlsession中,当会话结束时,缓存被清空,可能使用率不高,还会浪费内存。
二级缓存属于整个Namespace,存储在红色区域的数据会被所有sqlsession共享。
下面给出一个示例演示一级缓存 和二级缓存
xml:
一级缓存(默认开启的就是一级缓存)
测试代码LV1:
@Testpublic void testLv1Cache(){SqlSession sqlSession = null;try {sqlSession = MyBatisUtils.openSession();// 语句执行了两次,但是sql只执行了一次Goods goods = sqlSession.selectOne("goods.selectById", 1603);Goods goods1 = sqlSession.selectOne("goods.selectById", 1603);System.out.println(goods.hashCode()+" V S "+goods1.hashCode());System.out.println(goods.getTitle());} catch (Exception e) {e.printStackTrace();} finally {MyBatisUtils.closeSession(sqlSession);}}
效果:(两次调用,sql只执行了一次,说明第二次是缓存读取)
测试2:(二级缓存开启):两个sqlsession只有一次执行sql,原因是缓存在namesapce中,并且Cache Hit Ratio [goods]: 0.5说明使用了缓存读取数据
@Testpublic void testLv2Cache(){SqlSession sqlSession = null;try {sqlSession = MyBatisUtils.openSession();// 语句执行了两次,但是sql只执行了一次Goods goods = sqlSession.selectOne("goods.selectById", 1603);System.out.println(goods.hashCode());System.out.println(goods.getTitle());} catch (Exception e) {e.printStackTrace();} finally {sqlSession.commit();System.out.println("do 1");MyBatisUtils.closeSession(sqlSession);}try {sqlSession = MyBatisUtils.openSession();System.out.println("do 2");// 语句执行了两次,但是sql只执行了一次Goods goods = sqlSession.selectOne("goods.selectById", 1603);System.out.println(goods.hashCode());System.out.println(goods.getTitle());} catch (Exception e) {e.printStackTrace();} finally {MyBatisUtils.closeSession(sqlSession);}}
效果:
代表了缓存的清楚策略,当缓存对象达到上限后,自动触发对应算法对缓存对象进行清除
LRU --最近最久未使用:移除最长时间不被使用的对象(默认)
【LFU】–最近最少被使用:移除最少被使用的对象
FIFO–先进先出:按对象进入缓存的顺序来清理它们
SOFT–软引用:移除基于垃圾收集器状态和软引用规则的对象
WEAK–弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象
代表间隔多长时间自动清空缓存,单位毫秒,60000ms =10分钟
代表缓存存储上限,用于保存对象或者集合(1个集合是一个对象)的数量上限
设置为true,代表返回只读缓存,每次从缓存中取出的是缓存本身,执行效率较高
设置为false,代表每次取出的都是对象副本,每一次取出的对象都是不同的,这种安全性较高
在其它查询标签中,也有一些标签约束,例如
表示是否使用缓存,一次返回很多数据的sql一般设置为false,代表查询结果不放入缓存。
表示执行完sql后立即清除缓存
下面给出一个示例来阐释级联关系
班级和学生是 1:n关系,所以一般在学生表中都有班级的主键做外键
学生和学籍档案是1;1关系,所以一般都是主键关联
学生和课程是n:n关系,一般会有一张中间表存储关系数据
下面给出一个示例来看看MyBatis中oneToMany是怎么进行级联查询的
private List goodsDetails;
@Testpublic void testSelectOneToMany(){SqlSession sqlSession = null;try {sqlSession = MyBatisUtils.openSession();List list = sqlSession.selectList("goods.selectOneToMany");for (Goods goods : list) {System.out.println(goods.hashCode());System.out.println(goods.getTitle());}} catch (Exception e) {e.printStackTrace();} finally {sqlSession.commit();MyBatisUtils.closeSession(sqlSession);}}
最终结果:在执行完goods查询sql后会接着去查询details信息,进行了级联查询
那么我们如何完成从多的一方关联一的一方数据呢?接着往下看 多对一关联查询
与上面一对多关联查询步骤基本一致,只是在对应的查询xml中使用的标签不一样,如下:因为一对多时需要由一个值查出多个,所以采用的标签是 效果如下: 为了解决上述问题,MyBatis提供了分页插件PageHelper,那么如何使用分页插件呢,接着往下看。 下面逐步操作一遍 pom.xml增加 结果: 三层结构,外两层固定 MyBatis配置C3P0一共分3步 效果: 和C3P0的不同,Druid需要重写getDataSource方法。 xml: java代码: 使用MyBatis注解可以替代在xml中的标签,简化开发。
PageHelper分页插件
分页查询的麻烦事
PageHelper使用流程
引入依赖
mybatis-config.xml增加plugin配置
代码使用
@Testpublic void testSelectPage() {SqlSession sqlSession = null;try {sqlSession = MyBatisUtils.openSession();// startPage方法会自定将下一次查询进行分页PageHelper.startPage(2,10);Page
不同数据库分页的实现原理
Mysql分页
ORACLE分页
SQL Server 2000
SQL Server 2000+
MyBatis配置C3P0连接池
添加依赖
实现数据源C3P0化
package com.imooc.mybatis.datasource;import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;/*** C3P0与MyBatis兼容使用的数据源工厂类*/
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory{public C3P0DataSourceFactory() {this.dataSource = new ComboPooledDataSource();}
}
修改配置文件
MyBatis配置Druid连接池
添加依赖
实现数据源Druid化
package com.imooc.mybatis.datasource;import com.alibaba.druid.pool.DruidDataSource;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;import javax.sql.DataSource;
import java.sql.SQLException;public class DuridDataSourceFactory extends UnpooledDataSourceFactory {public DuridDataSourceFactory(){this.dataSource = new DruidDataSource();}@Overridepublic DataSource getDataSource(){try {((DruidDataSource)this.dataSource).init();} catch (SQLException e) {// TODO: handle exceptionthrow new RuntimeException(e);}return this.dataSource;}
}
修改配置文件
MyBatis批处理
@Testpublic void testBatchInsert(){SqlSession sqlSession = null;try {long bt =new Date().getTime();sqlSession = MyBatisUtils.openSession();List list = new ArrayList();for (int i = 0; i < 10000; i++) {Goods goods =new Goods();goods.setSubTitle("测试副标题"+i);goods.setTitle("测试标题"+i);goods.setCurrentPrice(500D);goods.setOriginalCost(1000d);goods.setDiscount(0.5d);goods.setIsFreeDelivery(1);goods.setCategoryId(43);list.add(goods);}sqlSession.insert("goods.batchInsert",list);sqlSession.commit();long et =new Date().getTime();System.out.println("执行时间为"+(et-bt)+"毫秒");} catch (Exception e) {e.printStackTrace();} finally {MyBatisUtils.closeSession(sqlSession);}}
MyBatis注解开发
MyBatis常用注解
下面具体示例使用注解开发应该怎么做配置mybatis-config.xml
创建DAO接口并使用注解开发
package com.mysql.mybatis.dao;import DTO.GoodsDTO;
import entity.Goods;
import org.apache.ibatis.annotations.*;import java.util.List;public interface GoodsDAO {@Select("select * from t_goods where current_price between #{min} and #{max} order by current_price limit 0,#{limit}")public List
测试类中获取Dao并执行方法
import DTO.GoodsDTO;
import com.mysql.mybatis.dao.GoodsDAO;
import entity.Goods;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import utils.MyBatisUtils;import java.util.List;public class MyBatisAnnociationTest {@Testpublic void testSelectByRange() {SqlSession sqlSession = null;try {sqlSession = MyBatisUtils.openSession();// 虽然持有的是接口 mybatis会根据配置信息动态生成实现类GoodsDAO goodsDAO = sqlSession.getMapper(GoodsDAO.class);List