Mybatis是一款优秀的持久层框架,主要就是封装了JDBC
将程序数据在持久状态和瞬时状态间转换的机制
优点:
- 解除了sql与程序代码的耦合,通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,sql和代码的分离,提高了可维护性
经常使用技巧
1.第一个入门小案例
废话不多说,直接上代码
1.搭建实现数据库
CREATE DATABASE `mybatis`; USE `mybatis`; DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(20) NOT NULL, `name` varchar(30) DEFAULT NULL, `pwd` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into `user`(`id`,`name`,`pwd`) values(1,'王二','123456'),(2,'张三','abcdef'),(3,'李四','987654');
2.导jar包
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version></dependency><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version></dependency>
3.编写Mybatis核心配置文件
<?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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/kuang/dao/userMapper.xml"/> </mappers></configuration>
4.编写Mybatis工具类(以前是jdbc,现在主要封装了一下,写一个sqlsession的工具类)
import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;import java.io.InputStream;public class MybatisUtils { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //获取SqlSession连接 public static SqlSession getSession(){ return sqlSessionFactory.openSession(); }}
5.创建实体类
public class User { private int id; //id private String name; //姓名 private String pwd; //密码 //构造,有参,无参 //set/get //toString() }
6.编写Mapper接口类
import com.kuang.pojo.User;import java.util.List; public interface UserMapper { List<User> selectUser();}
7.编写Mapper.xml配置文件
<?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="com.kuang.dao.UserMapper"> <select id="selectUser" resultType="com.kuang.pojo.User"> select * from user </select></mapper>
8.编写测试类
public class MyTest { @Test public void selectUser() { SqlSession session = MybatisUtils.getSession(); //方法一: //List<User> users = session.selectList("com.kuang.mapper.UserMapper.selectUser"); //方法二: UserMapper mapper = session.getMapper(UserMapper.class); List<User> users = mapper.selectUser(); for (User user: users){ System.out.println(user); } session.close(); }}
2.CRUD操作及配置解析
根据id查询用户
1.dao层接口添加方法
public interface UserMapper {
//查询全部用户
List<User> selectUser();
//根据id查询用户
User selectUserById(int id);
2.在xml中添加查询语句
<select id="selectUserById" resultType="com.kuang.pojo.User">
select * from user where id = #{id}
</select>
3.测试类中测试
@Test
public void tsetSelectUserById() {
SqlSession session = MybatisUtils.getSession(); //获取SqlSession连接
UserMapper mapper = session.getMapper(UserMapper.class);
User user = mapper.selectUserById(1);
System.out.println(user);
session.close();
}
根据密码和名字查询用户
方式一:直接根据字段来进行查找(场景:参数少)
//通过密码和名字查询用户
User selectUserByNP(@Param("username") String username,@Param("pwd") String pwd);
}
/*
<select id="selectUserByNP" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>
*/
方式二:使用万能的Map进行查找(场景:参数多)
User selectUserByNP2(Map<String,Object> map);
<select id="selectUserByNP2" parameterType="map" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>
方式三:直接用对象(场景:参数多)
User selectUserByNP2(User user);
<select id="selectUserByNP2" parameterType="com.kuang.pojo.User" resultType="com.kuang.pojo.User">
select * from user where name = #{username} and pwd = #{pwd}
</select>
小总结:
-
所有的增删改查操作都要提交事务
-
接口中的所有普通参数,尽量写上@Param,尤其是多个参数时,必须写上,
-
如果参数较多,则使用map,
-
为了规范操作,尽量把Parameter参数和resultType都写上
3.核心配置文件
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
<!-- 注意元素节点的顺序!顺序不对会报错 -->
4.ResultMap及分页
属性名与字段名不一致问题的解决
-
方法一:指定别名,别名和java实体类的属性名一致,pwd as password
-
方法二:使用结果集映射--》ResultMap
使用limit实现分页
#语法
SELECT * FROM table LIMIT stratIndex,pageSize
SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15
#为了检索从某一个偏移量到记录集的结束所有的记录行,可以指定第二个参数为 -1:
SELECT * FROM table LIMIT 95,-1; // 检索记录行 96-last.
#如果只给定一个参数,它表示返回最大的记录行数目:
SELECT * FROM table LIMIT 5; //检索前 5 个记录行
#换句话说,LIMIT n 等价于 LIMIT 0,n。
RowBounds分页
List<User> getUserByRowBounds();
<select id="getUserByRowBounds" resultType="user">
select * from user
</select>
@Test
public void testUserByRowBounds() {
SqlSession session = MybatisUtils.getSession();
int currentPage = 2; //第几页
int pageSize = 2; //每页显示几个
RowBounds rowBounds = new RowBounds((currentPage-1)*pageSize,pageSize);
//通过session.**方法进行传递rowBounds,[此种方式现在已经不推荐使用了]
List<User> users = session.selectList("com.kuang.mapper.UserMapper.getUserByRowBounds", null, rowBounds);
for (User user: users){
System.out.println(user);
}
session.close();
}
#{}和${}的区别
#{}的作用主要是替换预编译语句PrepareStatement中的占位符
${}的作用是直接进行字符串的替换
使用注解和配置文件的协同开发,才是Mybatis的最佳实践
5.一对多和多对一的处理
其实就是两个关键字的使用 association 和 collection,所以associationyon用于一对一和多对一,而collection用于一对多的关系
6.动态sql
直接上例子
select * from blog where title = #{title} and author = #{author}
-->
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog where
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
<!--注意set是用的逗号隔开-->
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id};
</update>
<select id="queryBlogChoose" parameterType="map" resultType="blog">
select * from blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
7.缓存
首先明白一个问题:为什么会使用缓存,减少和数据库交互的次数,减少系统开销,提高系统效率
-
Mybatis包含一个非常强大的查询缓存特性,他可以非常方便地定制和配置缓存,缓存可以极大的提升查询效率
-
mybatis中默认定义了两级缓存:一级缓存和二级缓存
-
默认情况下,只有一级缓存开启,sqlSession级别的缓存,也称为本地缓存
-
二级缓存需要手动开启和配置,他是基于namespace级别的缓存
-
为了提高扩展性,mybatis定义了缓存接口,可以通过实现Cache接口来定义二级缓存