MyBatis3官方
https://mybatis.org/mybatis-3/zh/getting-started.html
http://www.mybatis.cn/category/sjbt/
https://mvnrepository.com/search?q=mybatis
https://github.com/mybatis/mybatis-3/releases
所有的知识点从官网进行学习与验证,此文档仅拟一个框架丶
工程搭建
-
准备数据库(见配置文件,未实现SSL连接)
-
新建maven工程(删除src目录作为父工程,导入依赖)
-
新建module(maven工程)为子工程
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!--父工程-->
<groupId>com.hello</groupId>
<artifactId>mybatis-gfpz</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>mybatis-01</module>
<module>mybatis-02</module>
<module>mybatis-06</module>
<module>mybatis-07</module>
<module>mybatis-08</module>
</modules>
<!--导入依赖-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<!--使java中的配置文件可以被读到-->
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
xml配置
例: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>
<!--引入外部配置文件-->
<properties resource="db.properties">
<property name="username2" value="root"/>
<property name="password2" value="root"/>
</properties>
<settings>
<!--标准日志工厂实现-->
<!--<setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!--需要导包-->
<setting name="logImpl" value="LOG4J"/>
</settings>
<!--给实体类起别名,亦可通过实体类上加注解来起别名-->
<typeAliases>
<!-- <typeAlias type="com.hello.pojo.User" alias="User"/>-->
<package name="com.hello.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username2}"/>
<property name="password" value="${password2}"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<mapper class="com.hello.dao.TeacherMapper"/>
<mapper class="com.hello.dao.StudentMapper"/>
</mappers>
</configuration>
- mybatis可以配置多套环境,但是每个SqlSessionFactory只能选择一个环境
- mybatis默认的事务管理器是JDBC,默认的数据源是POOLED
- 可以通过properties属性来实现引用配置文件
- 类型别名用以减少完全限定名的冗余
- 基本类型的别名为下划线开头,否则就成了包装类
执行流程
插件 pagehelper
插件 Mybatis Plus
通用 Mapper
插件 Lombok
- Idea安装Lombok插件
- 项目中引入Lombok依赖
- @Data、@AllArgsConstructor、@NoArgsConstructor
xml映射文件
使用注解开发
关于@Param()
- 基本数据类型或String类型,需要加上
- 引用类型不需要加
- 如果只有一个基本类型,可以忽略,但是建议加上
- sql中引用的就是@Param()中设定的属性名
多对一
实体类
@Data
public class Student {
private int id;
private String name;
private Teacher teacher;
}
@Data
public class Teacher {
private int id;
private String name;
}
StudentMapper.xml
<mapper namespace="com.hello.dao.StudentMapper">
<!--方式2:按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname from student s,teacher t where s.tid = t.id
</select>
<!--对象,使用 association-->
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
<!--方式1:查询所有的学生,按照查询出来的学生的tid,寻找对应的老师 像子查询-->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
</mapper>
一对多
实体类
@Data
public class Student {
private int id;
private String name;
private int tid;
}
@Data
public class Teacher {
private int id;
private String name;
private List<Student> students;
}
接口
public interface TeacherMapper {
//获取指定老师及其对应所有学生的信息
Teacher getTeacher(@Param("tid") int id);
Teacher getTeacher2(@Param("tid") int id);
}
TeacherMapper.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.hello.dao.TeacherMapper">
<!--方式1:按照结果嵌套查询-->
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid,s.name sname,t.name tname,t.id tid
from teacher t,student s
where t.id=s.tid and t.id=#{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--集合,使用collection 集合中的泛型信息,使用ofType获取-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
<!--方式2:按照查询嵌套处理-->
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher where id=#{tid}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<!--集合,使用 collection 集合中的泛型信息,使用ofType获取-->
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from student where tid=#{tid};
</select>
</mapper>
一对多&多对一
- 一对多,一关联多,用association
- 多对一,一包含集合,用 collection
- javaType & ofType
缓存
- 大多数时候,我们的服务器与数据库之间都是执行的查询操作
- MyBatis 内置了事务性查询缓存机制,可以方便地配置和定制
- 不是每一次执行sql,mybatis都会区请求数据库,很多时候可以直接从缓存获取
- 默认情况下,只启用了本地的会话缓存(即一级缓存),它仅仅对一个会话中的数据进行缓存(session的生命周期内)
- 一级缓存就是一个map,session结束就没了(除非开启了二级缓存,map会被丢到二级缓存中)
- 缓存失效的情况
- 两次查不一样的内容
- 增删改之后,刷新缓存
- 不同的mapper去查
- 手动清理缓存sqlSession.clearCache();
- 要启二级缓存(也叫全局缓存),只需要在你的 SQL 映射文件中添加一行:
当然前提是cacheEnabled=true - 二级缓存,也只能在同一个mapper下有效
- 请求进来,应该是先找二级缓存,再找一级缓存
自定义缓存EhCache(使用方式就是标签配置)
EhCache 是一个`纯Java`的进程内`缓存框架`,具有快速、精干等特点,是Hibernate中默认CacheProvider。Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有`内存`和`磁盘`存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存servlet过滤器,支持REST和SOAP api等特点。
动态 SQL
- 根据前端来的不同的条件组合请求,生成不同的sql语句,起到复用sql的作用
- 所谓的动态sql,本质还是sql语句,只是我们可以在sql层面,去执行一个逻辑代码
- 熟练工
Java API
- SqlSessionFactoryBuilder对象是为了搞出SqlSessionFactory对象来,SqlSessionFactoryBuilder对象放到局部变量
- SqlSessionFactory对象需要放到全局变量中(类模板加载后,一直存在于内存中)
- SqlSession对象为每次连接到连接池的一次会话,用完需关闭;SqlSession的实例不是线程安全的,不要在类的静态变量或者成员变量中实例化它,而应在方法体中使用
这几个Handler主要用以:处理参数、处理结果集、处理类型转换
日志
根据项目选型来,上手即用
底层动态代理
引入mybati之前
public class UserDaoImpl implements UserDao{
private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory factory){
this.factory = factory;
}
public List<User> findAll() {
//1.获取sqlSession对象
SqlSession sqlSession = factory.openSession();
//2.调用selectList方法
List<User> list = sqlSession.selectList("com.example.dao.UserDao.findAll");
//3.关闭流
sqlSession.close();
return list;
}
}
引入之后,UserDaoImpl这一层变成了Mapper.xml,功能代码交给了代理对象实现
-->DeaultSqlSession.getMapper
-->Configuration.getMapper
-->MapperRegistry.getMapper
-->MapperProxyFactory.MapperProxy
-->mapperProxyFactory.newInstance(sqlSession);
-->MapperProxy
-->JDK动态代理必须实现的接口InvocationHandler.invoke()
-->MapperMethod.execute()、内部类SqlCommand和MethodSignature
-->回到了SqlSession中的接口调用
后期
还需要继续迭代
- 放在项目中进行熟练工
- 图例全部手工重构
- 实现现场教学,半小时演示纯手工打造航母