MyBatis框架入门(一)

目录

1.框架概述

1.1 三层架构

1.2 框架

2.Mybatis框架概述

2.1 JDBC的缺陷

2.2 Mybatis框架概述

3.Mybatis的入门案例

4.Mybatis中主要类的介绍

4.1 Resources类

4.2 SqlSessionFactoryBuilder类

4.3 SqlSessionFactory接口

4.4 SqlSession接口

5.关于入门案例的修改

5.1 传统dao的使用方式

5.2 使用Mybatis的动态代理


1.框架概述

1.1 三层架构

   三层架构包括界面层、业务逻辑层、数据访问层。

        ①界面层(表示层,视图层):主要功能是接受用户的数据,显示请求的处理结果。(jsp、

          html、servlet)

        ②业务逻辑层:接收表示传递过来的数据,检查数据,计算业务逻辑,调用数据访问层获取

          数据。

        ③数据访问层(持久层):与数据库打交道。主要实现对数据的增、删、改、查,将存储在数据

          库中的数据提交给业务层,同时将业务层处理的数据保存到数据库。

   三层对应的包

        ①界面层:controller包(XXXServlet类)

        ②业务逻辑层:service包(XXXService类)

        ③数据访问层:dao包(XXXDao类)

   三层中类的交互

        用户使用界面层--->业务逻辑层--->数据访问层--->数据库

   三层对应的处理框架

        界面层---servlet类---springmvc框架

        业务逻辑层---service类---spring框架

        数据访问层---dao类---mybatis框架

1.2 框架

   框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例件交互的方法,也可以将框架看成是可被应用开发者定制的应用骨架、模板。简单地说,框架其实是半成品软件,就是一组组件,供你使用来完成你自己的系统。框架是安全的、可复用的、不断升级的软件。

   框架中定义好了一些基础功能,可以在项目中加入自己的功能,而自己加入的功能也可以利用框架中写好的功能。

   框架特点

        ①框架一般不是全能的,不能做所有事情;

        ②框架是针对某一领域有效,特长在某一方面,比如mybatis做数据库操作强,但不擅长做其

          他的;

        ③框架是一个软件

2.Mybatis框架概述

2.1 JDBC的缺陷

   ①代码比较多,开发效率低;

   ②需要关注Connection、Statement、ResultSet对象的创建和销毁;

   ③对ResultSet查询的结果,需要自己封装为List;

   ④重复的代码比较多;

   ⑤业务代码和数据库的操作混在一起。

2.2 Mybatis框架概述

   mybatis框架,早期叫做ibatis,其源代码在github上。

   mybatis是MyBatis SQL Mapper Framework for Java(sql映射框架),包括:

        ①sql maper:sql映射。可以吧数据库表中的一行数据映射为一个java对象,即一行数据可以

          看作是一个java对象,操作这个对象,就相当于操作表中的数据。

        ②Data Access Objects(Daos):数据访问,对数据库执行增删改查。

   mybatis提供的功能

        ①提供了创建Connection、Statement、ResultSet的能力,不需要开发人员创建这些对象。

        ②提供了执行sql语句的能力,不用开发人员执行sql语句。

        ③提供了循环sql,把sql的结果转为java对象、List集合的能力。

                在JDBC中只能:

                        while (rs.next()) {
                                Student stu = new Student();
                                stu.setId(rs.getInt("id"));
                                stu.setName(rs.getString("name"));
                                stu.setAge(rs.getInt("age"));
                                //从数据库取出数据转为 Student 对象,封装到 List 集合
                                stuList.add(stu);
                         }

        ④提供了关闭资源的能力,不用自己手动关闭Connection、Statement、ResultSet。

   流程:开发人员提供sql语句---mybatis处理执行sql语句---开发人员得到List集合或Java对象(表中的数据)

   总结:mybatis是一个sql映射框架,提法对数据库的操作能力,相当于增强的JDBC。使用mybatis可以让开发人员集中精力写sql语句就可以了,不用关心Connection、Statement、ResultSet的创建、销毁以及sql语句的执行。

3.Mybatis的入门案例

   1.创建mysql数据库和表。数据库名springdb;表名student。

MyBatis框架入门(一)

   2.新建一个maven项目,骨架选择maven-archetype-quickstart即可。在pom.xml文件中加入mybatis、mysql驱动的依赖。

<!--mybatis依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.1</version>
</dependency>
<!--sql驱动依赖-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.9</version>
</dependency>

   3.创建实体类,Student类,用来保存表中的一行数据。实体类的包名叫domain或者entity

package com.bjpowernode.domain;
//推荐和表名一样,容易记忆
public class Student {
    //定义属性,目前要求是属性名和列名一样。
    private Integer id;
    private String name;
    private String email;
    private Integer age;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", age=" + age +
                '}';
    }
}

   4.创建数据访问层的dao接口,定义操作数据库的方法。包名叫做dao

package com.bjpowernode.dao;

import com.bjpowernode.domain.Student;
import java.util.List;
//接口操作Student表
public interface StudentDao {

    //查询Student表的所有数据
    public List<Student> selectStudents();

    //插入方法
    //参数:student,表示要插入到数据库的数据
    //返回值:int    表示执行insert操作后的影响数据库的行数(成功添加了几行数据 )
    public int insertStudent(Student student);
}

   5.创建一个mybatis使用的配置文件,叫做sql映射文件,用来写sql语句的。一般一个表一个sql映射文件,这个文件是xml文件。该文件写在dao接口所在的目录中(dao文件夹),文件名称和dao接口名称保持一致。StudentDao.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.bjpowernode.dao.StudentDao">
    <select id="selectStudents" resultType="com.bjpowernode.domain.Student">
       select id,name,email,age from student order by id
    </select>

    <!--
        select:表示查询操作。
        id:你要执行的sql语法的唯一标识,mybatis会使用这个id的值来找到要执行的sql语句
            可以自定义,但是要求你使用接口中的方法名称。

        resultType:表示结果类型的,是sql语句执行后得到ResultSet,遍历这个ResultSet得到java对象的类型。
                    值写的类型的全限定名称

    -->
    <select id="insertStudent">
        insert into student values (#{id},#{name},#{email},#{age})
    </select>
</mapper>
<!--
     sql映射文件(sql mapper):写sql语句的,mybatis会执行这些sql
     1.指定约束文件
          <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

       mybatis-3-mapper.dtd是约束文件的名称,扩展名是dtd的。

     2.约束文件的作用:限制,检查在当前文件中出现的标签、属性必须符合mybatis的要求

     3.mapper:是当前文件的根标签,必须的。
       namespace:叫做命名空间,唯一值的,可以是自定义的字符串。
                  要求使用dao接口的全限定名称

     4.在当前文件中可以使用特定的标签,表示数据库的特定操作。
        <select>:表示执行查询,select语句
        <update>:表示更新数据库的操作,就是在<update>标签中写的是update语句
        <insert>:表示插入,放的是insert语句
        <delete>:表示删除,执行的是delete语句
-->

   6.创建mybatis的主配置文件一个项目就一个主配置文件,主配置文件提供了数据库的连接信息和sql映射文件的位置信息。写在resources文件夹中。mybatis.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>
    <!--settings:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>
    <!--
         环境配置:数据库的连接信息
         default:必须和某个environment的id值一样。
                  告诉mybatis使用哪个数据库的连接信息,也就是访问哪个数据库。
    -->
    <environments default="mydev">
        <!--
            environment:一个数据库信息的配置,环境
            id:一个唯一值,自定义,表示环境的名称。
        -->
        <environment id="mydev">
            <!--
                 transactionManager:mybatis的事务类型
                 type:JDBC(表示使用jdbc中的Connection对象的commit,rollback做事务处理)
            -->
            <transactionManager type="JDBC"/>
            <!--
                 dataSource:表示数据源,连接数据库的
                 type:表示数据源的类型,POOLED表示使用连接池
            -->
            <dataSource type="POOLED">
                <!--
                    driver,url,username,password是固定的,不能自定义。
                -->
                <!--数据库的驱动类名-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <!--连接数据库的url字符串-->
                <property name="url" value="jdbc:mysql://localhost:3306/springdb"/>
                <!--访问数据库的用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>

        <!--表示线上的库,是项目真实使用的库-->
        <environment id="online">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/onlinedb"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!--sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--
            一个mapper标签指定一个文件的位置。
            从类路径开始的路径信息。 target/classes(类路径)
        -->
        <mapper resource="com/bjpowernode/dao/StudentDao.xml"/>
        <!--<mapper resource="com/bjpowernode/dao/SchoolDao.xml"/>-->
    </mappers>
</configuration>

<!--
     mybatis的主配置文件:主要定义了数据库的配置信息,sql映射文件的位置

     1.约束文件
        <!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

       mybatis-3-config.dtd:约束文件的名称

     2.configuration 根标签
-->

   7.创建使用mybatis类,通过mybatis访问数据库。

package com.bjpowernode;

import com.bjpowernode.domain.Student;
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;
import java.util.List;

public class MyApp {
    public static void main(String[] args) throws IOException {
        //访问mybatis,读取student数据
        //1.定义mybatis主配置文件的名称,从类路径的跟开始(target/classess)
        String config = "mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in  = Resources.getResourceAsStream(config);
        //3.创建了SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.[重要]获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = factory.openSession();
        //6.[重要]指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqiId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
        //7.执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqiId);
        //8.输出结果
        //studentList.forEach( stu -> System.out.println(stu));
        for (Student stu:studentList){
            System.out.println(stu);
        }
        //9.关闭SqlSession对象
        sqlSession.close();
    }
}
public class TestMybatis {
    //测试方法,测试功能
    @Test
    public void testInsert() throws IOException {
        //访问mybatis,读取student数据
        //1.定义mybatis主配置文件的名称,从类路径的跟开始(target/classess)
        String config = "mybatis.xml";
        //2.读取这个config表示的文件
        InputStream in  = Resources.getResourceAsStream(config);
        //3.创建了SqlSessionFactoryBuilder
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //4.创建SqlSessionFactory对象
        SqlSessionFactory factory = builder.build(in);
        //5.[重要]获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        //SqlSession sqlSession = factory.openSession();
        SqlSession sqlSession = factory.openSession(true);//自动提交事务
        //6.[重要]指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqiId = "com.bjpowernode.dao.StudentDao" + "." + "insertStudent";
        //7.执行sql语句,通过sqlId找到语句
        Student student = new Student();
        student.setId(1005);
        student.setName("关羽");
        student.setEmail("guanyu@163.com");
        student.setAge(20);
        int num = sqlSession.insert(sqiId,student);
        //mybatis默认不是自动提交事务的,所以在insert,update,delete后要手工提交事务
        //sqlSession.commit();
        //8.输出结果
        System.out.println("执行insert结果:" + num);
        //9.关闭SqlSession对象
        sqlSession.close();
    }
}

   8.创建一个工具类来实现前半部分重复的代码。

package com.bjpowernode.utils;

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 factory = null;

    static {
        String config = "mybatis.xml";
        try {
            InputStream in = Resources.getResourceAsStream(config);
            //创建SqlSessionFactory对象,使用SqlSessionFactoryBuilder
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取SqlSession的方法
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = null;
        if(factory != null){
            sqlSession = factory.openSession();//非自动提交事务
        }
        return sqlSession;
    }
}

   9.利用工具类来实现查询功能。

public class MyApp2 {
    public static void main(String[] args) throws IOException {
        //[重要]获取SqlSession对象,从SqlSessionFactory中获取SqlSession
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        //[重要]指定要执行的sql语句的标识。  sql映射文件中的namespace + "." + 标签的id值
        String sqiId = "com.bjpowernode.dao.StudentDao" + "." + "selectStudents";
        //执行sql语句,通过sqlId找到语句
        List<Student> studentList = sqlSession.selectList(sqiId);
        //输出结果
        //studentList.forEach( stu -> System.out.println(stu));
        for (Student stu:studentList){
            System.out.println(stu);
        }
        //9.关闭SqlSession对象
        sqlSession.close();
    }
}

   在该例子中并没有使用到dao接口,这个接口不是必须的,但是在我们之后的开发中都是利用这个接口中的方法来访问数据库,进行增删改查操作。 

4.Mybatis中主要类的介绍

4.1 Resources类

   Resources是mybatis中的一个类,负责读取主配置文件

        InputStream in = Resources.getResourceAsStream("mybatis.xml");

4.2 SqlSessionFactoryBuilder类

   负责创建SqlSessionFactory对象

        SqlSessionFactoryBuilder builder  = new SqlSessionFactoryBuilder();

        //创建SqlSessionFactory对象

        SqlSessionFactory factory = builder.build(in);

4.3 SqlSessionFactory接口

   重量级对象,程序创建一个该对象耗时比较长,使用资源比较多。在整个项目中,这个对象有一个就够了,因此可以利用工具类中的静态代码块来创建。

   SqlSessionFactory:接口。接口实现类:DefaultSqlSessionFactory。

   SqlSessionFactory作用: 获取SqlSession对象

        SqlSession sqlSession = factory.openSession();

   关于openSession()方法说明:

        1. openSession() :无参数的,获取是非自动提交事务的SqlSession对象

        2. openSession(boolean):

                openSession(true)  获取自动提交事务的SqlSession. 

                openSession(false)  非自动提交事务的SqlSession对象

4.4 SqlSession接口

   定义了操作数据的方法,例如selectOne()   selectList()   insert()   update()   delete()   commit()   rollback()。

   SqlSession接口的实现类DefaultSqlSession。

   使用要求: SqlSession对象不是线程安全的,需要在方法内部使用,在执行sql语句之前,使用openSession()获取SqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close()。这样能保证他的使用是线程安全的。

5.关于入门案例的修改

5.1 传统dao的使用方式

   1.dao接口:

package com.bjpowernode.dao;

import com.bjpowernode.domain.Student;

import java.util.List;

public interface StudentDao {
    List<Student> selectStudents();
    int insertStudent(Student student);
}

   2.dao接口的实现类:

package com.bjpowernode.dao.impl;

import com.bjpowernode.dao.StudentDao;
import com.bjpowernode.domain.Student;
import com.bjpowernode.util.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class StudentDaoImpl implements StudentDao {
    @Override
    public List<Student> selectStudents() {
        //获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlid = "com.bjpowernode.dao.StudentDao.selectStudents";
        //执行sql语句,使用SqlSession类的方法
        List<Student> students = sqlSession.selectList(sqlid);
        sqlSession.close();
        return students;
    }

    @Override
    public int insertStudent(Student student) {
        //获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlid = "com.bjpowernode.dao.StudentDao.insertStudent";
        //执行sql语句,使用SqlSession类的方法
        int nums = sqlSession.insert(sqlid,student);
        //提交事务
        sqlSession.commit();
        sqlSession.close();
        return nums;
    }
}

   3.测试方法:

public class TestMyBatis {
    @Test
    public void testSelectStudents(){
        //com.bjpowernode.dao.StudentDao
        StudentDao dao = new StudentDaoImpl();
        /*
             List<Student> students = dao.selectStudents(); 调用
             1.dao对象,类型是StudentDao,全限定名称是: com.bjpowernode.dao.StudentDao
               全限定名称和namespace是一样的。

             2.方法名称,selectStudents,这个方法名称就是mapper文件中的id值
               
               1和2获得的字符串拼接后就是之前我们需要使用的sqlid

             3.通过dao中方法的返回值类型也可以确定MyBatis要调用的SqlSession的方法
                  如果返回值类型是List,调用的是SqlSession.selectList() select方法
                  如果返回值类型是int,或者是非List的,看mapper文件中的标签是<insert>,<update>就会调用
                  SqlSession的insert,update等方法
             
             这样就发现通过一个方法调用可以获得以上信息,因此可以利用反射机制。

             mybatis的动态代理:mybatis根据dao的方法调用,获取执行sql语句的信息。
                               mybatis根据你的dao接口,创建出一个dao接口的实现类,并创建这个类的对象。
                               完成SqlSession调用方法,访问数据库。
                               所以不需要自己手写dao的实现类。mybatis会利用动态代理自动实现。
         */
        List<Student> students = dao.selectStudents();
        for(Student student : students){
            System.out.println(student);
        }
    }

    @Test
    public void testInsertStudent(){
        StudentDao dao = new StudentDaoImpl();
        Student student = new Student();
        student.setId(1006);
        student.setName("盾山");
        student.setEmail("dunshan@163.com");
        student.setAge(22);
        int nums = dao.insertStudent(student);
        System.out.println("添加对象的数量:" + nums);
    }
}

5.2 使用Mybatis的动态代理

   1.dao接口:

public interface StudentDao {
    List<Student> selectStudents();
    int insertStudent(Student student);
}

   2.利用动态代理的测试方法:

        SqlSession的对象有一个方法getMapper()

public class TestMyBatis {
    @Test
    public void testSelectStudents(){
        /**
         * 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
         * getMapper能获取dao接口对应的实现类对象。
         */
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);//利用反射机制
        //dao=com.sun.proxy.$Proxy2:JDK的动态代理
        System.out.println("dao=" + dao.getClass().getName());
        //调用dao的方法,执行数据库的操作
        List<Student> students = dao.selectStudents();
        for (Student student : students){
            System.out.println(student);
        }
        sqlSession.close();
    }

    @Test
    public void testInsertStudent(){
        Student student = new Student();
        student.setId(1007);
        student.setName("李飞");
        student.setEmail("lifei@163.com");
        student.setAge(22);
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        int nums = dao.insertStudent(student);
        sqlSession.commit();
        System.out.println("添加对象的数量:" + nums);
        sqlSession.close();
    }
}

PS:根据动力节点课程整理,如有侵权,联系删除。

上一篇:10.12JDBC之DAO实现类的优化


下一篇:springboot+mybatis+thymeleaf模板之经典小项目实战教程