为网站网站做推广彬县网新闻最新消息
目录
1. MyBatis 日志管理
1.1 日志概述
1.2 (logback)日志环境配置
01. pom.xml
02. 运行测试方法
03. 配置logback.xml文件
2. 动态SQL的使用
2.1 概述
2.2 goods.xml
2.3 testDynamicSQL()
2.4 实现效果
3. MyBatis 二级缓存
3.1 缓存范围 与 运行规则
3.2 测试一级缓存
3.3 sqlSession.commit() 强制清空 已有的缓存
3.4 开启二级缓存
(1)查询标签设置useCache="true"开启缓存:
(2)插入标签设置flushCache="true"清空缓存
4. 一对多 & 多对一 对象关联查询
4.1 oneToMany 对象关联查询
(1) 创建 GoodsDetail 实体类
(3)编写 goods_detail.xml 的 selectGoodsDetailByGoodsId 查询标签
(4) mybatis-config.xml 中添加配置
(4) 编写 goods.xml 的 rmGoodsOneToMany结果集
(5)编写 selectOneTo(Many 查询标签
(6) 编写 testOneToMany() 测试方法
(7)debug 效果
4.2 ManyToOne 对象关联查询
(1) 编写 goods_detail.xml 的结果集 rmGoodsDetailManyToOne
(2)编写多对一 查询selectManyToOne 标签
(3)编写测试类 testManyToOne()
(4)debug 效果
5. 分页查询插件PageHelper
5.0 base
(1) 分页查询的麻烦事
5.1 PageHelper
5.2 pageHelper 使用流程
(1) 引入依赖
(2)mybatis-config.xml 中增 Pagehelper 配置
(3)goods.xml 中添加分页查询标签
(4) 编写测试方法 testSelectPage()
(5) 封装实现
(6) 实现效果
6.Mybatis 配置 C3P0 连接池
6.1 引入 c3p0 依赖
6.2 创建C3P0 与 Mybatis 兼容使用的数据源工厂类
6.3 mybatis-config.xml 中配置C3P0 的相关连接信息
7. Mybatis 批处理 SQL
7.1 批量插入
(1)编写SQL标签
(2) 编写测试类
7.2 批量删除
(1) 编写SQL标签
(2)测试方法 testBatchDelete
8. MyBatis 注解开发
8.1 MyBatis 的常用注解
8.2 @Select
(1) 注释掉 mapper 标签
(2) 编写 GoodsDTO1
(3) 编写 GoodsDAO 接口
(4)调整 mybatis-config.xml
(5) 测试 @Select 注解
8.3 @Insert
(1)编写接口
(2)编写测试类
(3)测试testSelectAll()
1. MyBatis 日志管理
1.1 日志概述
1.2 (logback)日志环境配置
01. pom.xml
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency>
02. 运行测试方法
@Testpublic void testSelectByTitle02() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();Map param = new HashMap();param.put("title","'爱恩幼 孕妇护肤品润养颜睡眠面膜 100g'");List<Goods> list = sqlSession.selectList("goods.selectByTitleAndOrder", param);for(Goods goods: list){System.out.println(goods.getSubTitle() + ":" + goods.getDiscount());}}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
03. 配置logback.xml文件
<!--日志的输出级别:error: 错误 - 系统的故障日志warn: 警告 - 存在风险或使用不当的日志info: 一般性消息 ==》往上常用于 生产环境debug: 程序内部用于调试信息 ==》常用于 调试开发阶段trace: 程序运行的跟踪信息 -->
<?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>
2. 动态SQL的使用
2.1 概述
2.2 goods.xml
<!--动态SQL写法01--><select id="dynamicSQL" parameterType="java.util.Map" resultType="com.phdvb.mybatis.entity.Goods">select * from t_goodswhere1=1<if test = "categoryId != null">and categroy_id = #{categoryId}</if><if test = "currentPrice != null">and current_price < #{currentPrice}</if></select><!--动态SQL写法02<where>--><select id="dynamicSQL02" parameterType="java.util.Map" resultType="com.phdvb.mybatis.entity.Goods">select * from t_goods<where><if test = "categoryId != null">and category_id = #{categoryId}</if><if test = "currentPrice != null">and current_price < #{currentPrice}</if></where></select>
2.3 testDynamicSQL()
@Testpublic void testDynamicSQL() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();Map param = new HashMap();param.put("categoryId", 44);param.put("currentPrice", 500);// 查询条件List<Goods> list = sqlSession.selectList("goods.dynamicSQL02", param);for(Goods goods: list){System.out.println(goods.getTitle() + ":" +goods.getGoodsId() +goods.getCategoryId() + ":" + goods.getCurrentPrice());}}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
2.4 实现效果
3. MyBatis 二级缓存
3.1 缓存范围 与 运行规则
3.2 测试一级缓存
@Testpublic void testLvCache() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();Goods goods1 = sqlSession.selectOne("goods.selectById", 831);Goods goods2 = sqlSession.selectOne("goods.selectById", 831);System.out.println(goods1.hashCode() + "-"+ goods2.hashCode());}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
在同一个会话中,下一次重复的查询会使用重复记录
3.3 sqlSession.commit() 强制清空 已有的缓存
3.4 开启二级缓存
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="goods">
<!-- 开启二级缓存--><cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/>
@Testpublic void testLvCache02() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();Goods goods1 = sqlSession.selectOne("goods.selectById", 831);System.out.println(goods1.hashCode());}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}try{sqlSession = MyBatisUtils.openSession();Goods goods3 = sqlSession.selectOne("goods.selectById", 831);System.out.println(goods3.hashCode());}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
(1)查询标签设置useCache="true"开启缓存:
<!--单参数传递--><select id = "selectById" parameterType="Integer" resultType="com.phdvb.mybatis.entity.Goods" useCache="true">select * from t_goods where goods_id = #{value};</select>
(2)插入标签设置flushCache="true"清空缓存
<!--flushCache="true" 在执行sql后强制清空缓存--><insert id="insertGoods"parameterType="com.phdvb.mybatis.entity.Goods"useGeneratedKeys="true"keyProperty="goodsId"keyColumn="goods_id"flushCache="true">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})</insert>
4. 一对多 & 多对一 对象关联查询
4.1 oneToMany 对象关联查询
(1) 创建 GoodsDetail 实体类
package com.phdvb.mybatis.entity;public class GoodsDetail {private Integer gdId;private Integer goodsId;private String gdPicUrl;private Integer gdOrder;private Goods goods;public Integer getGdId() {return gdId;}public void setGdId(Integer gdId) {this.gdId = gdId;}public Integer getGoodsId() {return goodsId;}public void setGoodsId(Integer goodsId) {this.goodsId = goodsId;}public String getGdPicUrl() {return gdPicUrl;}public void setGdPicUrl(String gdPicUrl) {this.gdPicUrl = gdPicUrl;}public Integer getGdOrder() {return gdOrder;}public void setGdOrder(Integer gdOrder) {this.gdOrder = gdOrder;}public Goods getGoods() {return goods;}public void setGoods(Goods goods) {this.goods = goods;}
}
(2)goods新增 List<GoodsDetail> 结果集
public class Goods {private Integer goodsId; // 商品编号private String title; // 商品标题private String subTitle; // 子标题private Float originalCost; // 原始价格private Float currentPrice; // 当前价格private Float discount; // 折扣率private Integer isFreeDelivery; // 是否包邮(1-包邮, 0- 不包邮)private Integer categoryId; // 分类编号private List<GoodsDetail> goodsDetailList;
(3)编写 goods_detail.xml 的 selectGoodsDetailByGoodsId 查询标签
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="goodsDetail"><select id = "selectGoodsDetailByGoodsId" parameterType="Integer" resultType= "com.phdvb.mybatis.entity.GoodsDetail">select * from t_goods_detail where goods_id = #{value}</select></mapper>
(4) mybatis-config.xml 中添加配置
<mappers><mapper resource="mappers/goods.xml"/><mapper resource="mappers/goods_detail.xml"/></mappers>
</configuration>
(4) 编写 goods.xml 的 rmGoodsOneToMany结果集
<!-- 一对多 与 多对一 对象关联查询--><!--resultMap 可用于说明 一对多 或者 多对一 的映射逻辑id 是属性应用标志 | type 指向One 的实体(Goods)--><resultMap id="rmGoodsOneToMany" type="com.phdvb.mybatis.entity.Goods"><!-- 映射goods 对象的主键到 goods_id --><id column = "goods_id" property = "goodsId"></id><!--collection 的含义是1. 在 selectOneToMany 查询到结果后,2. 对所有的 Goods 对象遍历得到 goods_id 字段3. 将其带入到selectGoodsDetailByGoodsId 中查询将得到的“商品详情” 集合赋值给goodsDetails List对象--><collection property="goodsDetailList" select = "goodsDetail.selectGoodsDetailByGoodsId"column="goods_id"/></resultMap>
(5)编写 selectOneTo(Many 查询标签
<select id = "selectOneToMany" resultMap = "rmGoodsOneToMany">select * from t_goods limit 0, 2</select>
(6) 编写 testOneToMany() 测试方法
/*** 一对多对象 关联查询*/@Testpublic void testOneToMany() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();List<Goods> list = sqlSession.selectList("goods.selectOneToMany");for(Goods goods: list){System.out.println(goods.getTitle() + ":" + goods.getGoodsDetailList().size());}}catch(Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
(7)debug 效果
4.2 ManyToOne 对象关联查询
(1) 编写 goods_detail.xml 的结果集 rmGoodsDetailManyToOne
<resultMap id="rmGoodsDetailManyToOne" type="com.phdvb.mybatis.entity.GoodsDetail">
<!-- <id column = "gd_id" property="gdId"></id>--><result column = "goods_id" property = "goodsId"></result><association property="goods" select ="goods.selectById" column = "goods_id"/></resultMap>
(2)编写多对一 查询selectManyToOne 标签
<select id = "selectManyToOne" resultMap="rmGoodsDetailManyToOne">select * from t_goods_detail limit 0, 20</select>
(3)编写测试类 testManyToOne()
/*** 多对一 关联查询*/@Testpublic void testManyToOne() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();List<GoodsDetail> list = sqlSession.selectList("goodsDetail.selectManyToOne");for(GoodsDetail goodsDetail: list){System.out.println(goodsDetail.getGdId() + ":" +goodsDetail.getGoodsId()+ ":" + goodsDetail.getGdPicUrl() + goodsDetail.getGoods().getSubTitle());}}catch(Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
(4)debug 效果
5. 分页查询插件PageHelper
5.0 base
(1) 分页查询的麻烦事
5.1 PageHelper
官方链接:
MyBatis 分页插件 PageHelper
如何使用分页插件doc:
如何使用分页插件
5.2 pageHelper 使用流程
(1) 引入依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper</artifactId><version>5.1.8</version>
</dependency><!--sql 解析器-->
<dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>2.0</version>
</dependency>
(2)mybatis-config.xml 中增 Pagehelper 配置
<!--启用 Pagehelper 分页插件--><plugins><plugin interceptor="com.github.pagehelper.PageInterceptor"><!--设置数据库类型--><property name="helperDialect" value="mysql"/><!--设置分页合理化--><property name="reasonable" value="true"/></plugin></plugins>
(3)goods.xml 中添加分页查询标签
<!--将价格小于800的商品分页查询出来-->
<select id="selectPage" resultMap="com.phdvb.mybatis.entity.Goods">select * from t_goods where current_price < 800
</select>
(4) 编写测试方法 testSelectPage()
/*** PageHelper 分页查询*/@Testpublic void testSelectPage() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();/*startPage 方法会自动将 下一次查询进行分页*/PageHelper.startPage(3,15);Page<Goods> page = (Page) sqlSession.selectList("goods.selectPage");System.out.println("总页数:" + page.getPages()); //总页数:119System.out.println("总记录数:" + page.getTotal()); //总记录数:1774System.out.println("开始行号:" + page.getStartRow()); //开始行号:30System.out.println("结束行号:" + page.getEndRow()); //结束行号:45System.out.println("当前页码:" + page.getPageNum()); //当前页码:3List<Goods> list = page.getResult();for (Goods good : list) {System.out.println(good.getGoodsId() +"-"+ good.getSubTitle());}System.out.println();}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
(5) 封装实现
(6) 实现效果
6.Mybatis 配置 C3P0 连接池
6.1 引入 c3p0 依赖
<dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.4</version>
</dependency>
6.2 创建C3P0 与 Mybatis 兼容使用的数据源工厂类
package com.phdvb.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();}
}
6.3 mybatis-config.xml 中配置C3P0 的相关连接信息
<environment id="prod"><!-- 采用JDBC的方式对 数据库事务进行 commit/ rollback--><transactionManager type="JDBC"></transactionManager><!-- 采用连接池的方式管理数据库连接-->
<!-- <dataSource type="POOLED">-->
<!-- <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!-- <property name="url" value="jdbc:mysql://114.114.114.114:3303/phdvb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/>-->
<!-- <property name="username" value="root"/>-->
<!-- <property name="password" value="123456"/>-->
<!-- </dataSource>--><!--采用 C3P0 连接池的方式管理数据库连接--><dataSource type="com.phdvb.mybatis.datasource.C3P0DataSourceFactory"><property name="driverClass" value="com.mysql.jdbc.Driver"/><property name="jdbcUrl" value="jdbc:mysql://114.114.114.114:3303/phdvb?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai"/><property name="user" value="root"/><property name="password" value="123456"/><property name="initialPoolSize" value="5"/><property name="maxPoolSize" value="20"/><property name="minPoolSize" value="5"/></dataSource></environment>
7. Mybatis 批处理 SQL
Q1:
batchInsert 无法获取新增数据的 Id
Q2:
批量生成的SQL太长,可能会被服务器拒绝
7.1 批量插入
(1)编写SQL标签
<!--批处理SQL 一次插入多条SQL-->
<!-- 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>
(2) 编写测试类
@Testpublic void testBatchInsert() throws Exception{SqlSession session = null;try{long st = new Date().getTime();session = MyBatisUtils.openSession();List list = new ArrayList();for (int i = 0; i < 10000; i++ ){ //执行时间:3160毫秒
// for (int i = 0; i < 2; i++ ){ //执行时间:1970毫秒Goods goods = new Goods();goods.setTitle("测试商品"+ "i");goods.setSubTitle("测试子标题"+ "i");goods.setOriginalCost(300f + i);goods.setCurrentPrice(500f + i);goods.setDiscount(i * 0.0001f);goods.setIsFreeDelivery(1);goods.setCategoryId(43);list.add(goods);}session.insert("goods.batchInsert", list);session.commit(); // 提交事务long et = new Date().getTime();System.out.println("执行时间:" + (et - st) + "毫秒") ;}catch(Exception e){throw e;}finally{MyBatisUtils.closeSession(session);}}
7.2 批量删除
(1) 编写SQL标签
<!--批处理SQL 一次性删除多条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>
(2)测试方法 testBatchDelete
@Testpublic void testBatchDelete() throws Exception{SqlSession session = null;try{long st = new Date().getTime();session = MyBatisUtils.openSession();List list = new ArrayList();list.add(12685);list.add(12684);list.add(12683);list.add(12682);list.add(12681);session.delete("goods.batchDelete", list);session.commit();long et = new Date().getTime();System.out.println("执行时间:" + (et - st) + "毫秒") ;}catch(Exception e){throw e;}finally{MyBatisUtils.closeSession(session);}}
8. MyBatis 注解开发
将xml代码放入程序中,开发更加方便
8.1 MyBatis 的常用注解
8.2 @Select
(1) 注释掉 mapper 标签
(2) 编写 GoodsDTO1
package com.phdvb.mybatis.dto;public class GoodsDTO1 {private Integer goodsId;private String title;private Float currentPrice;public GoodsDTO1() {}public Integer getGoodsId() {return goodsId;}public void setGoodsId(Integer goodsId) {this.goodsId = goodsId;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}public Float getCurrentPrice() {return currentPrice;}public void setCurrentPrice(Float currentPrice) {this.currentPrice = currentPrice;}
}
(3) 编写 GoodsDAO 接口
package com.phdvb.mybatis.dao;import com.phdvb.mybatis.entity.Goods;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;import java.util.List;public interface GoodsDAO {@Select(" select * from t_goods where current_price between #{min} and #{max} limit 0, #{limt}")public List<Goods> selectByPriceRange(@Param("min") Float min, @Param("max") Float max, @Param("limt") Integer limt);
}
(4)调整 mybatis-config.xml
<!--注解开发时。可以不写 ~.xml--><mappers>
<!-- <mapper resource="mappers/goods.xml"/>--><!--注解开发写法一-->
<!-- <mapper class = "com.phdvb.mybatis.dao.GoodsDAO"/>--><!--注解开发写法二--><package name="com.phdvb.mybatis.dao"/></mappers>
(5) 测试 @Select 注解
// 测试 @Select 注解@Testpublic void testAnnotationSelectRange() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();GoodsDAO goodsDAO = sqlSession.getMapper(GoodsDAO.class);List<Goods> list = goodsDAO.selectByPriceRange(100f, 500f, 20);System.out.println(list.size());}catch (Exception e){throw e;}finally{MyBatisUtils.closeSession(sqlSession);}}
8.3 @Insert
(1)编写接口
@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> 获取id@SelectKey(statement = "select last_insert_id()", before = false, keyProperty = "goodsId", resultType = Integer.class)public int insert(Goods goods);
(2)编写测试类
// 测试 @Insert 注解@Testpublic void testInsert() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();Goods goods = new Goods();goods.setTitle("测试Insert goods");goods.setSubTitle("测试Insert Sub goods");goods.setOriginalCost(200f);goods.setCurrentPrice(100f);goods.setDiscount(0.55f);goods.setIsFreeDelivery(1);goods.setCategoryId(43);GoodsDAO goodsDAO = sqlSession.getMapper(GoodsDAO.class);int num = goodsDAO.insert(goods);sqlSession.commit();System.out.println(goods.getGoodsId());}catch (Exception e){if(sqlSession != null){sqlSession.rollback();}}finally{MyBatisUtils.closeSession(sqlSession);}}
(3)测试testSelectAll()
@Testpublic void testSelectAll() throws Exception{SqlSession sqlSession = null;try{sqlSession = MyBatisUtils.openSession();GoodsDAO goodsDAO = sqlSession.getMapper(GoodsDAO.class);List<GoodsDTO1> list = goodsDAO.selectAll();System.out.println(list.size()); //11936}catch (Exception e){throw e;}finally {MyBatisUtils.closeSession(sqlSession);}}