优秀的数据持久层框架
最新版本Maven配置:
1.搭建工程:org.mybatis mybatis 3.5.7
mybatis依赖+数据库连接依赖
org.mybatis mybatis 3.5.7 mysql mysql-connector-java 8.0.17
因为mybatis留有对数据库的接口,需要实现对应数据库(如mysql)的接口包,此时mybatis依赖搭建完成。
2.配置文件:主标签:< configuration>< /configuration>
可选配置:
1.< properties >设置properties文件(可选)可用来存放配置文件需要用到的数据,如:数据库连接的相关信息。配置之后可以在配置文件中使用${key}来代指。
2.< settings >基本设置(可选)可用来设置SQL日志
3.< typeAliases>类型别名配置(可选)
必须配置:
1.< environments> 数据库环境配置
2.< mappers> mapper文件注册,***Mapper.xml 文件要想生效,这是必须的
3. mapper.xml:
< mapper namespace=" "> 写对应的mapper接口全路径。
**二级子标签分别对应于数据库的 增删查改(CRUD) **
id需要完全对应本文件对应的mapper接口中的方法名,resultType为返回类型 且只有select标签有
重要知识点: 1.mapper接口方法中的参数传递给xml文件:
取值有两种方式**KaTeX parse error: Expected 'EOF', got '#' at position 11: {表达式}**和**#̲{表达式}**,其中经常使用的…{}只是进行拼接,不能够有效的防止SQL注入。
在括号中的表达式书写,分为四种情况:
1.接口方法的参数只有一个基本类型的参数时:表达式可以取任意命名,都将会自动匹配。
2.单个引用类型的参数时,可以直接使用该类对象的属性名,mybatis将会自动注入。重点:map作为参数,可以直接以key作为键值对。
3.当有多个参数时,参数的表达式默认为arg0argN-1,param1paramN。当对应参数位置为引用数据类型时,可以直接使用对应的表达式.(例如:arg1.name,param2.name)
4.在接口方法的参数上使用@Param注解,注解中可以声明一个别名,该别名可以被xml文件自动识别到,从而进行注入(推荐)
注:在SQL语言中需要使用拼接的可以使用SQL自带的concat方法。**
如:LIKE CONCAt(’%’, #{params.name}, ‘%’)
2.主键回填主键回填分为两种情况:一种是主键自增长的主键回填,第二种是主键由数据库随机生成(uuid)。
注意order的属性值。
1.主键自增长:
接口中的方法:
public interface ArticleMapper {
int addArticle(@Param("article") Article article);
}
map.xml文件
SELECT LAST_INSERT_ID() INSERT INTO score(name, score)VALUES(#{score.name}, #{score.score})
2.主键由数据库自动生成
3.结果映射:SELECT REPLACE(UUID(),'-','') INSERT INTO article(id, title, content, author) VALUES (#{article.id}, #{article.title}, #{article.content}, #{article.author})
4.级联查询
级联查询需要使用结果映射。
一对一级联查询需要使用< association>标签
一对多级联查询需要使用< collection>标签
5.标签的应用SELECT tno, tname FROM a_teacher SELECT cno id, cname name FROM a_course WHERe tno = #{tid}
sql和include标签:SQL语言的重用,
username, password,salt,sex,address SELECT FROM `user` WHERe username = #{abcde}
if标签:在test中写上符合java的布尔表达式,
AND name LIKE CONCAt('%', #{params.name}, '%')
where标签:嵌套在if之外,能够自动添加where和忽略第一个and或者or关键字,
set标签:在updata语句中使用,也是嵌套在if之外,能够自动添加set和忽略SQL语句的后缀,如逗号,可以动态选择修改属性,
name = #{s.name}, score = #{s.score}, AND id = #{s.id}
trim标签:可以代替 where 标签和 set 标签
foreach标签:循环标签经常用于sql含有in或not in的常见
4. Mybatis缓存
- 缓存的定义
缓存就是存储在内存中的临时数据,将用户经常查询的数据放在缓存(内存)中,用户再次查询数据的时候就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,能够提高查询效率,解决了高并发系统的性能问题
- 缓存的优势
减少和数据库的交互次数,减少系统开销,提高系统效率
- 缓存使用场景
经常查询并且不经常改变的数据
- Mybatis 缓存
mybatis包含一个非常强大的查询缓存特性,可以非常方便地定制和配置缓存,缓存可以极大地提高查询效率
mybatis系统默认定义了两级缓存:一级缓存和二级缓存
-
一级缓存:
默认情况下只有一级缓存开启(SqlSession级别的缓存,也称为本地缓存),同一个 SqlSession 执行多次同构查询时,结果将放入一级缓存。
-
二级缓存:
需要手动开启和配置,它是基于SqlSessionFactory级别的缓存,同一个 SqlSessionFactory 构建的 SqlSession 发起的多次同构查询,如果SqlSession关闭,则会将数据保存在二级缓存中
4.2 Mapper缓存配置
4.3 二级缓存失效
二级缓存缓存数据的前提是查询的 SqlSession 关闭,如果 SqlSession 没有关闭,那么数据将不会进入二级缓存,再次进行同构查询时,二级缓存由于没有数据,查询将进入数据库,造成二级缓存失效的现象。另一种情况是,当前查询的 SqlSession 已经关闭,数据也进入了二级缓存,但在下一次查询之前,如果中间发生了更新操作,该操作更新的数据在的二级缓存中存在,那么二级缓存也将失效。
5.分页插件 PageHelper 1. 如何获取PageHelper官方网站: https://pagehelper.github.io/
最新版本Maven配置:
2. 插件配置com.github.pagehelper pagehelper 5.3.0
3. 测试分页
@Test
public void paginationTest(){
SqlSession sqlSession = MybatisUtil.openSession();
//从Sql会话中获取Mapper接口的代理实例
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map params = new HashMap<>();
params.put("sex", 1);
params.put("name", "理");
params.put("address", "千");
//设置分页
PageHelper.startPage(1, 5);
List users = userMapper.retrieveUsers(params);
PageInfo pageInfo = new PageInfo<>(users);//将分页查询的结果集保存在PageInfo对象中
System.out.println("总条数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
//当前页数据展示
pageInfo.getList().forEach(System.out::println);
}
6.配置数据源 Druid
Druid 是阿里巴巴开源平台上的一个项目,是性能最好的数据库连接池,如何在Mybatis中配置该数据源呢?
com.alibaba druid 1.2.8
创建 DruidDataSourceFactory, 并继承 PooledDataSourceFactory,并替换数据源
public class DruidDataSourceFactory extends PooledDataSourceFactory {
public DruidDataSourceFactory() {
this.dataSource = new DruidDataSource();//替换数据源
}
}
...
最后,再附上一个mybatis的测试工具类和测试案例(注:一般在开发项目时使用ssm整合mybatis,放入ioc容器,不需要单独管理。)
public class MybatisUtil {
//构造器私有化
private MybatisUtil(){}
//生产SQL会话的工厂
private static SqlSessionFactory factory;
//静态代码块初始化
static {
//创建SQL会话工厂构建者 SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
try{
//读取配置文件
InputStream is = Resources.getResourceAsStream("config.xml");
//构建者根据配置文件来构建SqlSessionFactory
factory = builder.build(is);
} catch (IOException e){
throw new RuntimeException("配置文件读取错误");
}
}
public static SqlSession openSession(){
SqlSession session = factory.openSession();
//这下面是对session的代理模式
//获取SqlSession的字节码文件对象
Class aClass = SqlSession.class;
//获取上下文类加载器
ClassLoader loader = aClass.getClassLoader();
//将字节码文件对象放入数组
Class[] interfaces = { aClass };
//
InvocationHandler handler = (proxy,method,args)-> {
//获取方法名
String name = method.getName();
if (name.equals("close")){
//如果是调用close方法,先提交事务
try {
session.commit();
} catch (Exception e){
//提交事物出错,回滚事务
session.rollback();
}
}
//执行方法,返回方法执行的结果
return method.invoke(session,args);
};
//此时返回一个SqlSession的代理
return (SqlSession) Proxy.newProxyInstance(loader,interfaces,handler);
}
}
@Test
public void searchStudentTest(){
//获取SqlSession的代理对象
SqlSession sqlSession = MybatisUtil.openSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//执行查询
StudentCondition studentCondition = new StudentCondition("川", 24);
Student student = mapper.searchStudent(studentCondition);
sqlSession.close();
System.out.println(student);
}



