SSM框架学习----Mybatis(1)

Mybatis框架学习----上

  • Mybatis 框架
    • 一. mybatis概述
      • 1. 框架
      • 2. 三层架构
      • 3. 持久层的解决方案
      • 3. Mybatis
    • 二. 环境搭建
      • 1. 安装maven仓库以及环境配置
      • 2. 创建**maven项目**,配置三个路径地址
      • 3. 在**pom文件**中导入需要的依赖:mybatis坐标,mysql坐标,日志以及Junit坐标
      • 4. 注意
    • 三. Mybatis入门案例
      • 1. 实现步骤
      • 2. 案例分析
      • 3. xml读取以及实现的原理
      • 4. 自定义mybatis的案例分析
      • 5. 基于注解配置的查询所有操作

Mybatis 框架

一. mybatis概述

1. 框架

软件开发的一套解决方案,不同的框架用于解决不同的问题,框架中封装了许多细节,开发者可以使用极为简单的方式来实现功能,大大提高了开发效率。

2. 三层架构

  • 表现层:用于展示数据
  • 业务层:处理业务需求
  • 持久层:和数据库交互

SSM框架图式
SSM框架学习----Mybatis(1)_第1张图片

3. 持久层的解决方案

  • JDBC技术:

    Connection

    PreparedStatement

    ResultSet

  • Spring的JdbcTemplate:Spring对JDBC的简单封装

  • Apache的DBUtils:类似于JdbcTemplate

以上这些都不是框架,仅仅是工具类。

3. Mybatis

是一个基于java的持久层框架,内部封装了JDBC,使开发者只需要关注sql语句本身,而不需要花费去处理加载驱动,创建连接,创建Statement对象等繁杂的过程。 通过XML或者注解的方式将要执行的各种Statement进行配置,通过java对象和Statement的动态参数进行映射执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。

采用ORM思想实现了结果集的封装:

ORM Object Relational Mapping 对象关系映射

将数据库表和实体类以及实体类的属性对应起来,通过操作实体类来实现操作数据库表。

User类 User表
id id
user_name user_name

保证实体类中的属性和数据库表的字段名称一致。

二. 环境搭建

1. 安装maven仓库以及环境配置

  1. 安装maven仓库,并在本地创建maven repository文件夹,用来存放需要下载的maven依赖;修改maven文件夹下面的conf/setting.xml文件中的localRepository为本地创建的maven repository文件夹路径,在高级系统配置中添加maven的环境变量,MAVEN_HOME,并且增加path环境变量,如下:

SSM框架学习----Mybatis(1)_第2张图片
SSM框架学习----Mybatis(1)_第3张图片
SSM框架学习----Mybatis(1)_第4张图片

2. 创建maven项目,配置三个路径地址

SSM框架学习----Mybatis(1)_第5张图片

Maven home path为安装好的maven根路径,User settings file为修改maven文件夹中的settings.xml的路径,Local rrepository为本地的maven文件夹根路径

3. 在pom文件中导入需要的依赖:mybatis坐标,mysql坐标,日志以及Junit坐标

SSM框架学习----Mybatis(1)_第6张图片

在src/main/java中创建package:com.huzhen.domain,在该包下创建实体类user,以及创建dao包,在下面创建user interface接口,定义需要实现的抽象方法;

在src/main/resources中创建SqlMapConfig.xml映射文件:mysql环境,事务类型,数据源,以及4个数据库基本信息, 指定映射配置文件的位置;

在resources中创建com.huzhen.dao创建UserDaoImpl.xml:
SSM框架学习----Mybatis(1)_第7张图片

select id即为user interface的抽象方法

4. 注意

  • 1.创建UserDaoImpl.xml是为了与UserInterface保持一致,在mybatis中将持久层的操作接口名和映射文件也叫作:Mapper,则UserDaoImpl与UserMapper是一致的。
  • 2.在idea中创建目录,和package是不一样的,包在创建时,com.huzhen.dao是三级结构,需要每次创建一个package,而不是一起创建,尽量不要创建成一个名为com.huzhen.dao的一级目录
  • 3.Mybatis的映射配置文件位置必须与dao接口的包结构相同,即接口在java下的dao包下,配置文件xml在resources的dao包下
  • 4.映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
  • 5.映射配置文件的操作配置,id属性必须是dao接口的抽象方法名
  • 当345点被满足后,在开发中就无须在写dao接口的实现类

三. Mybatis入门案例

1. 实现步骤

  • 读取配置文件SqlMapConfig.xml,返回一个InputStream对象is;
  • 使用SqlSessionFactoryBuilder类创建对象builder,使用builder来创建SqlSession对象session;
  • 使用SqlSession来创建Dao接口的代理对象
  • Dao接口 对象名 = Session.getMapper(Dao接口.class);
  • 执行Dao接口中的抽象方法;
  • 释放资源,session.close(); is.close();

具体代码如下:

        /*
        直接使用下面的动态代理来执行sql语句,会发生错误:A query was run and no Result Maps were found for the Mapped Statement 'com.huzhen.domain.dao.UserInterface.findAll'.
        It's likely that neither a Result Type nor a Result Map was specified.
        原因在于:查询语句的返回值需要与指定的实体类进行对应,所以需要配置resultType
         */
        SqlSession session = null;
        InputStream is = null;
        // 创建工厂实现类的细节忽略,而使用SqlSessionFactoryBuilder类来创建SqlSession对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        try {
            // 这里使用的是相对路径来读取配置文件,一般不采用这种
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactory factory = builder.build(is);
            // 使用工厂生产SqlSession对象
            session = factory.openSession();
            // 使用SqlSession来创建Dao接口的的代理对象
            UserInterface userDao = session.getMapper(UserInterface.class);
            // 使用代理对象执行方法
            List<User> users = userDao.findAll();
            for(User user : users){
                System.out.println(user);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(session != null){
                session.close();
            }
            try {
                if(is != null){
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

而基于注解来替换Dao接口的配置文件:

将UserDao.xml移除,在dao接口的方法findAll上使用@Select注解,并且指定sql语句,同时需要在SqlMapConfig.xml中的mapper配置处,使用class属性来指定Dao接口的全限定类名。

在实际开发中,均不采用dao实现类的方式,无论使用XML还是注解进行配置,但是Mybatis是支持写dao实现类的

2. 案例分析

SSM框架学习----Mybatis(1)_第8张图片

  • 在读取配置文件时采用相对路径或者绝对路径都不太可行,采用类加载器,只能读取类路径的配置文件,或者使用ServerletContext对象的getRealPath()方法来读取。
  • 创建工厂mybatis使用了构建者(builder)模式:将对象的构建细节隐藏,使用者直接调用方法即可拿到对象,优点在于解耦来降低类之间的依赖关系。
  • 生产SqlSession使用了工厂模式
  • 创建Dao接口实现类实现了代理模式,优点在于不修改源码的基础上对已有方法增强

3. xml读取以及实现的原理

请添加图片描述
SSM框架学习----Mybatis(1)_第9张图片
SSM框架学习----Mybatis(1)_第10张图片

拥有数据库的信息,可以创建Connection对象;

拥有mapper即拥有映射配置信息;

拥有sql语句,可以获取PreparedStatement来执行Sql语句,以及查询集结果封装的类型

读取配置文件,用到解析XML技术,dom4j来解析xml文件

(selectList method)

				1) 根据配置文件信息创建Connection对象:注册确驱动,获取连接
				2) 获取预处理对象PreparedStatement,获取sql语句并且执行
				3) 执行查询,返回一个ResultSet对象:ResultSet res = preparedStatement.executeQuery();
				4) 遍历结果集用于封装
List<E> list = new ArrayList<>();
while(res.next()){

E element = xxxx; 
// 反射来实现结果集的对象封装
(E element = (E) Class.forName(“全限定类名”).newInstance();)

list.add(element);	}

element的实例化: 使用resultType中的全限定类名来反射得到一个user对象

封装:将res的每个内容都添加到element中,实体类属性与表中的列名是一致的,于是可以将表的列名看成是实体类的属性名,可以使用反射的方式根据名称来获取每个属性并赋值。

关于映射信息:包含两个部分----执行的sql语句和封装结果集的全限定类名,将这两个信息组成定义成一个对象。

使用map来存储:key存储nameSpace以及select id,value存储String sql以及String domainClassPath

Key Value
nameSpace String sql
select id String domainClassPath

请添加图片描述

根据Dao接口的字节码文件来创建dao的代理对象

Public <T> T getMapper(Class<T> daoInterfaceClass){

	Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

}

注意:

  • ClassLoader类加载器:使用的和被代理对象是相同的类加载器
  • Class[] interfaces代理对象要实现的接口:和被代理对象实现相同的接口
  • InvocationHeadler如何代理:增强的方法,需要自己提供,此处是一个InvocationHandler接口,需要写一个接口的实现类,在实现类中调用selectList方法

SSM框架学习----Mybatis(1)_第11张图片

4. 自定义mybatis的案例分析

使用mybatis能做什么? 创建代理对象和在代理对象中调用selectList方法

有哪些类和接口需要关注?

  • class Resources
  • class SqlSessionFactoryBuilder
  • interface SqlSessionFactory
  • interface SqlSession

具体流程为:

  • io中的Resources方法读取配置文件得到InputStream信息

  • 交给构建者SqlSessionFactoryBuilder,使用工具类构建了一个工厂对象

  • 工厂对象调用其openSession方法,创建代理对象
    ClassLoader类加载器:使用的和被代理对象是相同的类加载器,代理的接口是谁,
    就使用其getClassLoader的类加载器

    Class[] interfaces代理对象要实现的接口:和被代理对象实现相同的接口

    InvocationHandler如何代理:增强的方法,需要自己提供,此处是一个InvocationHeadler接口
    需要写一个接口的实现类,在实现类中调用selectList方法

  • 在session方法里面去实现创建代理对象和查询操作

SSM框架学习----Mybatis(1)_第12张图片

5. 基于注解配置的查询所有操作

  • 在SqlMapConfig.xml中的mapper属性中改成class = “dao接口的全限定类名”

SSM框架学习----Mybatis(1)_第13张图片

  • 在Dao接口的方法名上写上注解和sql语句,由于没有使用mybatis依赖,因此需要自定义实现Select注解

请添加图片描述
SSM框架学习----Mybatis(1)_第14张图片

  • 这里的value表示取得的sql语句,并且在XMLConfiguration类中执行的是LoadMapperAnnotation方法:
private static Map<String,Mapper> loadMapperAnnotation(String daoClassPath)throws Exception{
        //定义返回值对象
        Map<String,Mapper> mappers = new HashMap<String, Mapper>();

        //1.得到dao接口的字节码对象
        Class daoClass = Class.forName(daoClassPath);
        //2.得到dao接口中的方法数组,由于dao接口下可能存在多个方法,因此返回的是一个Method数组
        Method[] methods = daoClass.getMethods();
        //3.遍历Method数组
        for(Method method : methods){
            //取出每一个方法,判断是否有select注解
            boolean isAnnotated = method.isAnnotationPresent(Select.class);
            if(isAnnotated){
                //创建Mapper对象
                Mapper mapper = new Mapper();
                //取出注解的value属性值
                Select selectAnno = method.getAnnotation(Select.class);
                String queryString = selectAnno.value();
                mapper.setQueryString(queryString);
                //获取当前方法的返回值,还要求必须带有泛型信息
                Type type = method.getGenericReturnType();// List
                //判断type是不是参数化的类型
                if(type instanceof ParameterizedType){
                    //强转
                    ParameterizedType ptype = (ParameterizedType)type;
                    //得到参数化类型中的实际类型参数
                    Type[] types = ptype.getActualTypeArguments();
                    //取出第一个
                    Class domainClass = (Class)types[0];
                    //获取domainClass的类名
                    String resultType = domainClass.getName();
                    //给Mapper赋值
                    mapper.setResultType(resultType);
                }
                //组装key的信息
                //获取方法的名称
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String key = className+"."+methodName;
                //给map赋值
                mappers.put(key,mapper);
            }
        }
        return mappers;
    }

你可能感兴趣的:(java&框架,java,maven,intellij-idea,mybatis,ssm)