Mybatis3丶

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

所有的知识点从官网进行学习与验证,此文档仅拟一个框架丶

image-20201117171423565

工程搭建

  • 准备数据库(见配置文件,未实现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属性来实现引用配置文件
  • 类型别名用以减少完全限定名的冗余
  • 基本类型的别名为下划线开头,否则就成了包装类

img

执行流程

image-20201117171638945

插件 pagehelper

pagehelper

插件 Mybatis Plus

通用 Mapper

插件 Lombok

  • Idea安装Lombok插件
  • 项目中引入Lombok依赖
  • @Data、@AllArgsConstructor、@NoArgsConstructor

xml映射文件

image-20201117171327622

使用注解开发

关于@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的实例不是线程安全的,不要在类的静态变量或者成员变量中实例化它,而应在方法体中使用

image-20201117170554536

这几个Handler主要用以:处理参数、处理结果集、处理类型转换

image-20201117170056585

日志

根据项目选型来,上手即用

底层动态代理

引入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中的接口调用

后期

还需要继续迭代

  • 放在项目中进行熟练工
  • 图例全部手工重构
  • 实现现场教学,半小时演示纯手工打造航母
击石乃有火,不击元无烟!!
原文地址:https://www.cnblogs.com/rain2020/p/14002072.html