为什么需要MyBatis?
作者学习笔记,供复习使用,如有不对!望批评指出!转载请 标注
为什么需要MyBatis?
一个优秀的持久层框架。
典型特点:利用xml将sql与程序进行解耦,便于维护。
在jdbc的基础上进行了封装和延申
为了和数据库连接交互,我们通常将sql语句 写在java代码中,但是这种方式不利于后期维护,MyBatis就可以将sql语句和java代码分离,方便后期因为需求变动而对sql语句进行修改。
引入单元测试:
下载jar包
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
编写代码对已有功能进行检测
添加@Test注解
@Test
public void testSelectByPriceRange() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Map param = new HashMap();
param.put("min",100);
param.put("max" , 500);
param.put("limt" , 10);
List<Goods> list = session.selectList("goods.selectByPriceRange", param);
for(Goods g:list){
System.out.println(g.getTitle() + ":" + g.getCurrentPrice());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
Mybatis:
1.下载jar包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
3.创建全局唯一的SqlSessionFactory对象,创建sqlsession对象
sqlsession对象使用JDBC方式与数据库进行交互。提供CRUD方法。
/**
* MyBatisUtils工具类,创建全局唯一的SqlSessionFactory对象
*/
public class MyBatisUtils {
//利用static(静态)属于类不属于对象,且全局唯一
private static SqlSessionFactory sqlSessionFactory= null;
//利用静态块在初始化类时实例化sqlSessionFactory
static {
Reader reader = null;
try {
reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory= new SqlSessionFactoryBuilder().build(reader);
} catch (IOException e) {
e.printStackTrace();
//初始化错误时,通过抛出异常ExceptionInInitializerError通知调用者
throw new ExceptionInInitializerError(e);
}
}
/**
* openSession创建一个新的SqlSession对象
* @return SqlSession对象
*/
public static SqlSession openSession(){
return sqlSessionFactory.openSession();
}
/**
*释放一个有效的SqlSession对象
* @paramsession准备释放SqlSession对象
*/
public static void closeSession(SqlSession session){
if(session != null){
session.close();
}
}
}
2.Mybatis环境配置:mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"<http://mybatis.org/dtd/mybatis-3-config.dtd>">
<configuration>
<settings>
<!-- goods_id ==> goodsId驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--启用Pagehelper分页插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--设置数据库类型-->
<property name="helperDialect" value="mysql"/>
<!--分页合理化-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
<!--设置默认指向的数据库-->
<environments default="dev">
<!--配置环境,不同的环境不同的id名字-->
<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://localhost:3306/babytun?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>
</environment>
<environment id="prd">
<!--采用JDBC方式对数据库事务进行commit/rollback -->
<transactionManager type="JDBC"></transactionManager>
<!--采用连接池方式管理数据库连接-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.1.155:3306/babytun?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!--告知mybatis该配置文件的存在-->
<mappers>
<mapper resource="mappers/goods.xml"/>
<mapper resource="mappers/goods_detail.xml"/>
</mappers>
</configuration>
案例:
/**
* select查询语句执行
* @throwsException
*/
@Test
public void testSelectAll() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
**//sqlsession是mybatis的核心对象 用来执行语句**
List<Goods> list = session.selectList("goods.selectAll");
for(Goods g : list){
System.out.println(g.getTitle());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
/**
* 传递多个SQL参数
* @throws Exception
*/
@Test
public void testSelectByPriceRange() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Map param = new HashMap();
param.put("min",100);
param.put("max" , 500);
param.put("limt" , 10);
List<Goods> list = session.**selectList**("goods.selectByPriceRange", param);
for(Goods g:list){
System.out.println(g.getTitle() + ":" + g.getCurrentPrice());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
***List<GoodsDTO> list = session.selectList("goods.selectGoodsDTO");***
***Goods goods = session.selectOne("goods.selectById", 739);
int num = session.insert("goods.insert", goods);
int num = session.update("goods.update" , goods);
session.delete("goods.batchDelete", list);***
mappers配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"<http://mybatis.org/dtd/mybatis-3-mapper.dtd>">
<mapper namespace="goodsDetail">
<select id="selectByGoodsId" parameterType="Integer"
resultType="com.imooc.mybatis.entity.GoodsDetail">
select*from t_goods_detail where goods_id = #{value}
</select>
<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>
</mapper>
*parameterType="Integer" //输入参数 #{value}来获取
parameterType="java.util.Map"
<select id="selectByPriceRange" parameterType="java.util.Map" resultType="com.imooc.mybatis.entity.Goods">
select * from t_goods
where
current_price between #{min} and #{max}
order by current_price
limit 0,#{limt}
</select> //与map当中的key值进行对应 ,map当中的每一个key在sql当中必须使用。
parameterType="com.imooc.mybatis.entity.Goods" 传入的是对象
**resultType="com.imooc.mybatis.entity.GoodsDetail" //结果集***
主要掌握sql语句的写法和结果集
查询:<select>
<!--单参数传递,使用parameterType指定参数的数据类型即可,SQL中#{value}提取参数-->
<select id="selectById" parameterType="Integer" resultType="com.imooc.mybatis.entity.Goods">
select*from t_goods where goods_id = #{value}
</select>
@Test
public void testSelectById() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Goods goods = session.**selectOne**("goods.selectById" , 1603);
System.out.println(goods.getTitle());
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
<!--多参数传递时,使用parameterType指定Map接口,SQL中#{key}提取参数-->
<select id="selectByPriceRange" parameterType="java.util.Map" resultType="com.imooc.mybatis.entity.Goods">
select*from t_goods
where
current_price between #{min} and #{max}
order by current_price
limit 0,#{limt}
</select>
/**
* 传递多个SQL参数
* @throws Exception
*/
@Test
public void testSelectByPriceRange() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Map param = new HashMap();
param.put("min",100);
param.put("max" , 500);
param.put("limt" , 10);
List<**Goods**> list = session.**selectList**("goods.selectByPriceRange", param);
for(Goods g:list){
System.out.println(g.getTitle() + ":" + g.getCurrentPrice());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
//如何用对象的方式保存关联查询的结果呢??
resultMap将查询结果映射为复杂的java类型对象
dto是对原来java对象的扩展。用来传输数据的。不要改变实体类!
<!--结果映射-->
<resultMap id="rmGoods" type="com.imooc.mybatis.dto.GoodsDTO">
<!--设置主键字段与属性映射-->
<id property="goods.goodsId" column="goods_id"></id>
<!--设置非主键字段与属性映射-->
<result property="goods.title" column="title"></result>
<result property="goods.originalCost" column="original_cost"></result>
<result property="goods.currentPrice" column="current_price"></result>
<result property="goods.discount" column="discount"></result>
<result property="goods.isFreeDelivery" column="is_free_delivery"></result>
<result property="goods.categoryId" column="category_id"></result>
<result property="category.categoryId" column="category_id"></result>
<result property="category.categoryName" column="category_name"></result>
<result property="category.parentId" column="parent_id"></result>
<result property="category.categoryLevel" column="category_level"></result>
<result property="category.categoryOrder" column="category_order"></result>
<result property="test" column="test"/>
</resultMap>
<select id="selectGoodsDTO" resultMap="rmGoods">
select g.* , c.*,'1' as test from t_goods g , t_category c
where g.category_id = c.category_id
</select>
/**
* **利用ResultMap进行结果映射**
* @throws Exception
*/
@Test
public void testSelectGoodsDTO() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
List<**GoodsDTO**> list = session.**selectList**("goods.selectGoodsDTO");
for (GoodsDTO g : list) {
System.out.println(g.getGoods().getTitle());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
public class GoodsDTO {
private Goods goods = new Goods();
private Category category = new Category();
private String test;
public Goods getGoods() {
return goods;
}
public void setGoods(Goods goods) {
this.goods = goods;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
新增:<insert>开启事务!配置设置
<insert id="insert" parameterType="com.imooc.mybatis.entity.Goods" 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})
**//回传自动产生的id号,适用于任何数据库**
<selectKey resultType="Integer" keyProperty="goodsId" order="AFTER">
select last_insert_id(
</selectKey>
</insert>
/**
* 新增数据
* @throws Exception
*/
@Test
public void testInsert() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Goods goods = new Goods();
goods.setTitle("测试商品");
goods.setSubTitle("测试子标题");
goods.setOriginalCost(200f);
goods.setCurrentPrice(100f);
goods.setDiscount(0.5f);
goods.setIsFreeDelivery(1);
goods.setCategoryId(43);
//insert()方法返回值代表本次成功插入的记录总数
int num = session.insert("goods.insert", goods);
*session.commit();//提交事务数据*
System.out.println(goods.getGoodsId());
}catch (Exception e){
if(session != null){
session.rollback();//回滚事务
}
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
修改:开启事务!配置设置
<update id="update" parameterType="com.imooc.mybatis.entity.Goods">
UPDATE t_goods
SET
title = #{title} ,
sub_title = #{subTitle} ,
original_cost = #{originalCost} ,
current_price = #{currentPrice} ,
discount = #{discount} ,
is_free_delivery = #{isFreeDelivery} ,
category_id = #{categoryId}
WHERE
goods_id = #{goodsId}
</update>
/**
* 更新数据
* @throws Exception
*/
@Test
public void testUpdate() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
**//先查询再修改!!!不推荐手动赋值!!!**
**Goods goods = session.selectOne("goods.selectById", 739);
goods.setTitle("更新测试商品");**
int num = session.update("goods.update" , goods);
session.commit();//提交事务数据
}catch (Exception e){
if(session != null){
session.rollback();//回滚事务
}
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
删除:开启事务!配置设置
/**
*删除数据
* @throwsException
*/
@Test
public void testDelete() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
int num = session.delete("goods.delete" , 739);
session.commit();//提交事务数据
}catch (Exception e){
if(session != null){
session.rollback();//回滚事务
}
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
<delete id="delete" parameterType="Integer">
delete from t_goods where goods_id = #{value}
</delete>
Mybatis预防sql注入攻击:
使用#{}预编译传值,预防sql注入
${}文本替换
/**
*预防SQL注入
* @throwsException
*/
@Test
public void testSelectByTitle() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Map param = new HashMap();
/*
${}原文传值
select * from t_goods
where title = '' or 1 =1 or title = '【德国】爱他美婴幼儿配方奶粉1段800g*2罐 铂金版'
*/
/*
#{}预编译
select * from t_goods
where title = "'' or 1 =1 or title = '【德国】爱他美婴幼儿配方奶粉1段800g*2罐 铂金版'"
*/
param.put("title","'' or 1=1 or title='【德国】爱他美婴幼儿配方奶粉1段800g*2罐 铂金版'");
param.put("order" , " order by title desc");
List<Goods> list = session.selectList("goods.selectByTitle", param);
for(Goods g:list){
System.out.println(g.getTitle() + ":" + g.getCurrentPrice());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
Mybatis高级特性
1.日志管理:(非特有的)
引入jar包
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
就可以使用啦!!
也可以自定义信息,利用配置文件:在resources新建一个日志文件:logback.xml
?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:根据参数数据动态组织sql的技术
<select id="dynamicSQL" parameterType="java.util.Map" resultType="com.imooc.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>
/**
* 动态SQL语句
* @throws Exception
*/
@Test
public void testDynamicSQL() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Map param = new HashMap();
param.put("categoryId", 44);
param.put("currentPrice", 500);
//查询条件
List<Goods> list = session.selectList("goods.dynamicSQL", param);
for(Goods g:list){
System.out.println(g.getTitle() + ":" +
g.getCategoryId() + ":" + g.getCurrentPrice());
}
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
3.Mybatis二级缓存:查询速度更快
一级缓存默认开启,缓存范围sqlSession会话。
二级缓存手动开启,属于范围Mapper namespace。
二级缓存开启配置在mybatis-config.xml当中进行配置。
二级缓存运行规则 二级开启后默认所有查询操作均使用缓存 写操作commit提交时对该namespace缓存强制清空 配置useCache=false可以不用缓存 配置flushCache=true代表强制清空缓存
/**
*测试一级缓存,利用日志输出查看!!!
* @throwsException
*/
@Test
public void testLv1Cache() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Goods goods = session.selectOne("goods.selectById" , 1603);
Goods goods1 = session.selectOne("goods.selectById" , 1603);
System.out.println(goods.hashCode() + ":" + goods1.hashCode());
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
try{
session = MyBatisUtils.openSession();
Goods goods = session.selectOne("goods.selectById" , 1603);
**session.commit();//commit提交时对该namespace缓存强制清空**
Goods goods1 = session.selectOne("goods.selectById" , 1603);
System.out.println(goods.hashCode() + ":" + goods1.hashCode());
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
/**
*测试二级缓存
* @throwsException
*/
@Test
public void testLv2Cache() throws Exception {
SqlSession session = null;
try{
session = MyBatisUtils.openSession();
Goods goods = session.selectOne("goods.selectById" , 1603);
System.out.println(goods.hashCode());
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
try{
session = MyBatisUtils.openSession();
Goods goods = session.selectOne("goods.selectById" , 1603);
System.out.println(goods.hashCode());
}catch (Exception e){
throw e;
}finally {
MyBatisUtils.closeSession(session);
}
}
4.多表级联查询
一对多:
<!--
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>
/**
* 一对多对象关联查询
* @throws Exception
*/
@Test
public void testOneToMany() throws Exception {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
List<Goods> list = session.selectList("goods.selectOneToMany");
for(Goods goods:list) {
System.out.println(goods.getTitle() + ":" + goods.getGoodsDetails().size());
}
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(session);
}
}
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> goodsDetails;
多对一:
//在多的一方中增加一的实体
public class GoodsDetail {
private Integer gdId;
private Integer goodsId;
private String gdPicUrl;
private Integer gdOrder;
private Goods goods;
<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>
/**
* 测试多对一对象关联映射
*/
@Test
public void testManyToOne() throws Exception {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
List<GoodsDetail> list = session.selectList("goodsDetail.selectManyToOne");
for(GoodsDetail gd:list) {
System.out.println(gd.getGdPicUrl() + ":" + gd.getGoods().getTitle());
}
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(session);
}
}
5.整合c3p0连接池
mybatis默认使用自己的连接池
引用:
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.4</version>
</dependency>
<!--采用连接池方式管理数据库连接-->
//连接配置的名称也是固定的。!
<!--<dataSource type="POOLED">-->
<dataSource type="com.imooc.mybatis.datasource.C3P0DataSourceFactory">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/babytun?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"/>
/**
* C3P0与MyBatis兼容使用的数据源工厂类
*/
public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {
public C3P0DataSourceFactory(){
this.dataSource = new ComboPooledDataSource();
}
}
6.批处理:劣势:无法获取回传的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>
<!--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>
<!--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>
**
* 批量删除测试
* @throws Exception
*/
@Test
public void testBatchDelete() throws Exception {
SqlSession session = null;
try {
long st = new Date().getTime();
session = MyBatisUtils.openSession();
List list = new ArrayList();
list.add(1920);
list.add(1921);
list.add(1922);
session.delete("goods.batchDelete", list);
session.commit();//提交事务数据
long et = new Date().getTime();
System.out.println("执行时间:" + (et - st) + "毫秒");
// System.out.println(goods.getGoodsId());
} catch (Exception e) {
if (session != null) {
session.rollback();//回滚事务
}
throw e;
} finally {
MyBatisUtils.closeSession(session);
}
}
}
7.分页插件PageHelper:
PageHelper使用流程
maven引入PageHelper与jsqlparser:
- <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>
mybatis-config.xml增加Plugin配置:
<!--启用Pagehelper分页插件-->
- <plugins>
- <plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--设置数据库类型-->
<property value="mysql" name="helperDialect"/>
<!--分页合理化-->
<property value="true" name="reasonable"/>
</plugin>
</plugins>
代码中使用PageHelper.startPage()自动分页
@Test
/**
* PageHelper分页查询
*/
public void testSelectPage() throws Exception {
SqlSession session = null;
try {
session = MyBatisUtils.openSession();
//*startPage方法会自动将下一次查询进行分页*/
PageHelper.startPage(2,10);
Page<Goods> page = (Page) session.selectList("goods.selectPage");
System.out.println("总页数:" + page.getPages());
System.out.println("总记录数:" + page.getTotal());
System.out.println("开始行号:" + page.getStartRow());
System.out.println("结束行号:" + page.getEndRow());
System.out.println("当前页码:" + page.getPageNum());
List<Goods> data = page.getResult();//当前页数据
for (Goods g : data) {
System.out.println(g.getTitle());
}
System.out.println("");
} catch (Exception e) {
throw e;
} finally {
MyBatisUtils.closeSession(session);
}
}
8.注解开发!!!注解开发写一篇走起!
MyBatis常用注解
注解 对应XML 说明
@Insert <insert> 新增SQL
@Update <update> 更新SQL
@Delete <delete> 删除SQL
@Select <select> 查询SQL
@Param -- 参数映射
@Results <resultMap> 结果映射
@Result <id><result> 字段映射