Mybatis入门

Mybatis入门1.后端框架概述

1.1. 框架简介

1.2. 后端框架分类

2. Mybatis入门

2.1. 概述

2.2. Mybatis快速入门

2.3. CRUD操作

2.4. Mybatis工作原理

2.5. Mapper的获取实现原理

3. Mybatis核心配置文件

3.1. 核心配置文件结构

3.2. 属性文件

3.3. 类型别名

3.4. 常规配置获取自动生成的键

3.5. 插件配置之分页插件

3.6. 环境配置

1.后端框架概述

1.1. 框架简介

框架就是为了快速开发而提供好的项目半成品,类似写简历时提供的模板;框架存在的意义为了解决一些开发中典型的问题:

  • 重复代码问题

  • 代码之间的耦合问题

  • 提供一些预定好的工具减少重复轮子的制造

1.2. 后端框架分类

JavaEE中需要学习到的框架种类繁多:

  • ORM框架

    • DBUtils(自主研发)

    • Hibernate(重量级ORM框架) EJB->EJB3.0->JPA(java persistence API)

      session.save(obj)
      session.delete(obj)
      session.get(id)
          
      // HQL:hibernate Query Language 面向对象
      // from User 面向实体类的查询(非数据库) 
    • Mybatis(轻量级ORM框架)ibatis->Mybatis

      sql语句由程序员自己控制
      提供丰富的关联映射操作方式
      动态sql语句等
    • SpringData JPA(基于JPA的ORM实现)

  • MVC框架 (Model模型-View视图-Controller(Servlet))

    • struts1(SUN第一个MVC)

    • Webwork(非官方的MVC框架)

    • struts2(在webwork框架基础上发展而来)

    • springMVC(基于Spring的web解决方案)

  • 日志框架

  • 权限框架

  • 微服务框架

  • ....

EJB -> EJB3 ->JPA(java持久化API)

SSH: Struts2 + Spring + Hibernate

SSM:SpringMVC + Spring + Mybatis

SpringBoot: 一键启动

2. Mybatis入门

2.1. 概述

官网地址:mybatis – MyBatis 3 | 简介

Mybatis是基于JDBC实现的一套轻量级ORM(对象关系映射)解决方案,将所有的原始JDBC代码进行深度封装,只提供简单的API就能轻松实现数据持久化,MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录,支持自定义SQL语句,支持存储过程。

Mybatis框架提供了比Hibernate更为灵活的数据持久化操作(将关键的SQL语句交给程序员自己控制)

2.2. Mybatis快速入门

  1. 添加mybatis相关依赖

    <!-- mybatis依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    ​
    <!-- mysql依赖 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>
    ​
    <!--junit4依赖-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13</version>
        <scope>test</scope>
    </dependency>
    ​
    <!--lombok依赖-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
    </dependency>

  2. 准备数据库表(tbuser)

    CREATE TABLE `tbuser` (
    `id`  int(11) NOT NULL AUTO_INCREMENT ,
    `username`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
    `age`  int(11) NULL DEFAULT NULL ,
    `sex`  char(2) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
    `password`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ,
    `status`  int(11) NULL DEFAULT 0 ,
    PRIMARY KEY (`id`)
    )

  3. 创建实体类(User.java)

    @Data
    public class User {
    ​
        private int id;
        private String username;
        private String password;
        private int age;
        private String sex;
        private int status;
    ​
    }

  4. 创建核心配置文件(resources/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>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <!-- 数据源配置 -->
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                </dataSource>
            </environment>
        </environments>
        <!--    配置核心映射文件-->
        <mappers>
            <mapper resource="mappers\UserMapper.xml"/>
        </mappers>
    </configuration>

  5. 创建Mapper接口(DAO接口)

    /**
     * DAO层(mybatis中的Mapper)
     */
    public interface UserMapper {
    ​
        boolean insertUser(User user);
    ​
    }

  6. 创建与Mapper接口配套的XXXMapper.xml文件(UserMapper.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.softeem.dao.UserMapper">
    ​
        <insert id="insertUser">
            insert into tbuser(username,password,sex,age)
            values(#{username},#{password},#{sex},#{age})
        </insert>
    ​
    </mapper>

  7. 测试类

    public class UserMapperTest {
    ​
        @Test
        public void insertUser() throws IOException {
    ​
            String config = "mybatis-config.xml";
            //加载核心配置文件为一个流
            InputStream is = Resources.getResourceAsStream(config);
            //构建一个SqlSessionFactory
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            //创建session
            SqlSession session = factory.openSession();
    ​
            //获取Mapper对象(DAO)
            UserMapper mapper = session.getMapper(UserMapper.class);
    ​
            User user = new User();
            user.setUsername("softeem");
            user.setPassword("123456");
            user.setAge(18);
            user.setSex("女");
    ​
            boolean b = mapper.insertUser(user);
            //提交事务
            session.commit();
            assertTrue(b);
        }
    }

    注意事项:

    • 映射文件和Mapper接口之间的关系

     

     

2.3. CRUD操作

通过以上的配置,Mybatis的基本框架结构就已经搭建完毕,过程虽繁琐,但是接下来需要实现一套完整的CRUD只需要编写Mapper接口方法和Mapper.xml文件即可轻松实现:

 

对以上功能进行单元测试:

package com.softeem.dao;
​
import com.softeem.entity.User;
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 org.junit.Before;
import org.junit.Test;
​
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
​
import static org.junit.Assert.*;
​
public class UserMapperTest {
​
    private UserMapper mapper;
​
    @Before
    public void beforeConfig() throws IOException {
        String config = "mybatis-config.xml";
        //加载核心配置文件为一个流
        InputStream is = Resources.getResourceAsStream(config);
        //构建一个SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        //创建session 参数表示是否自动提交事务
        SqlSession session = factory.openSession(true);
        //获取Mapper对象(DAO)
        mapper = session.getMapper(UserMapper.class);
    }
​
    @Test
    public void insertUser() {
        User user = new User();
        user.setUsername("jack");
        user.setPassword("1222");
        user.setAge(16);
        user.setSex("女");
        boolean b = mapper.insertUser(user);
        assertTrue(b);
    }
​
    @Test
    public void deleteById() {
        assertTrue(mapper.deleteById(5));
    }
​
    @Test
    public void updatePwd() {
        User user = new User();
        user.setId(4);
        user.setPassword("111222333");
        assertTrue(mapper.updatePwd(user));
    }
​
    @Test
    public void selectById() {
        User user = mapper.selectById(4);
        System.out.println(user);
        assertNotNull(user);
    }
​
    @Test
    public void selectAll() {
        List<User> users = mapper.selectAll();
        users.forEach(System.out::println);
        assertNotNull(users);
    }
}

2.4. Mybatis工作原理

 

工作流程解析

  1. 读取相关的配置文件(mybatis-config.xml、*Mapper.xml)成为一个Configuration对象

  2. 通过Configuration对象构建SqlSessionFactory对象

  3. 由SqlSessionFactory获取SqlSession对象

  4. 通过SqlSession获取相应的Mapper对象(DAO对象)

  5. 通过mybatis提供Mappered Statements来对数据库进行相关操作(CRUD)

2.5. Mapper的获取实现原理

  1. 调用SqlSession的getMapper方法,并且向方法中传递需要获取的对象类型(UserMapper.class),SqlSession使用的实现类是org.apache.ibatis.session.defaults.DefaultSqlSession

  1. 根据读取到的配置对象,调用Configuration中提供的getMapper()获取实例

  1. 在Configuration类中,通过调用Mapper注册器(MapperRegistry

 

  1. 通过Mapper注册器工厂创建一个代理实例MapperProxy 

  1. 通过MapperProxyFactory对象执行newInstance()方法获取对应的Mapper实例,本质上使用的JDK动态代理实现对象的获

精华:Mybatis中Mapper接口的实现类是由JDK的动态代理技术实现(23种设计模式之一:代理模式)

3. Mybatis核心配置文件

3.1. 核心配置文件结构

Mybatis的核心配置文件(mybatis-config.xml)的配置项主要包含:

3.2. 属性文件

使用属性文件配置可以简单在配置文件中通过取值表达式获取属性信息,例如:

  • 属性文件(jdbc.properties)

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC
    jdbc.user=root

  • 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="jdbc.properties">
            <property name="jdbc.password" value="123456"/>
        </properties>
    ​
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <!-- 数据源配置 -->
                <dataSource type="POOLED">
                    <!--使用取值表达式获取属性值-->
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.user}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
        <!--    配置核心映射文件-->
        <mappers>
            <mapper resource="mappers\UserMapper.xml"/>
        </mappers>
    </configuration>

3.3. 类型别名

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写:

<typeAliases>
    <package name="com.softeem.entity"/>
</typeAliases>

以上代码的意思指的是将com.softeem.entity包下的所有实体类都默认提供一个别名,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名

如果需要对某个自定义别名,可以通过@Alias(别名)方式在类上方注解,例如:

@Alias("user")
public class User{
...
}

使用类型别名之后,映射文件(XXXMapper.xml)中就可以直接使用类型别名:

<mapper namespace="com.softeem.dao.UserMapper">
​
    <insert id="insertUser" parameterType="user">
        insert into tbuser(username,password,sex,age)
        values(#{username},#{password},#{sex},#{age})
    </insert>
​
    <select id="selectById" resultType="user">
        select * from tbuser where id=#{id}
    </select>
​
    <select id="selectAll" resultType="user">
        select * from tbuser
    </select>
​
    <select id="selectCount" resultType="int">
        select count(*) from tbuser
    </select>
</mapper>

以上parameterTyperesultType都可以直接使用别名

Mybatis中也同时为一些内置数据类型提供了别名,如下:

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

3.4. 常规配置获取自动生成的键

Mybatis核心配置文件中提供了一个<settings>标签用于进行一些常规的配置:缓存,日志,自动键等,具体参考官方文档设置

这里通过一个案例介绍settings的部分配置:

  • 如何获取自动生成的主键值

    通常对于一些包含自动递增的表来说,执行插入操作时可能需要获取自动生成的键,此时可以通过mybatis的settings中其中一个配置来实现:

    属性名说明取值默认值
    useGeneratedKeys允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true, 将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(Derby)。true | falseFalse

    具体使用流程如下:

    1. 在核心配置文件中添加useGeneratedKeys属性:

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE configuration
              PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-config.dtd">
      <configuration>
      ​
          <properties>
              ...
          </properties>
      ​
      <!--    常规配置-->
          <settings>
              <!--允许自动生成主键:配合映射文件-->
              <setting name="useGeneratedKeys" value="true"/>
          </settings>
          
      ​
          <typeAliases>
              ...
          </typeAliases>
      ​
          <environments default="dev">
              ...
          </environments>
      ​
          <mappers>
              ....
          </mappers>
      </configuration>

    2. 在映射文件中使用useGeneratedKeys属性和keyProperty属性配置在<insert>标签中:

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.softeem.lession01.dao.IUserMapper">
          
          <!-- 执行插入时获取自动生成的键,键值会自动设置给对象中的指定属性 -->
          <insert id="insertGetKey" useGeneratedKeys="true" keyProperty="id">
              insert into user(username,password,birthday)
              values(#{username},#{password},#{birthday})
          </insert>
          
      </mapper>

      对应的Mapper接口方法:

      Long insertGetKey(User user);
    3. 测试代码

      @Test
      public void insertGetKey() {
          User user = new User();
          user.setUsername("curry");
          user.setPassword("curry123");
          user.setBirthday(new java.sql.Date(System.currentTimeMillis()));
          //返回值表示为影响的数据行数
          Long line = userMapper.insertGetKey(user);
          System.out.println(line);
          //自动生成的主键会默认包含在user对象中
          System.out.println(user.getId());
      }

3.5. 插件配置之分页插件

Mybatis中需要实现分页操作,可以使用第三方的分页插件(PagerHelper)轻松实现(官方地址)使用流程如下:

  1. 导入分页插件的依赖

    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.0.3</version>
    </dependency>

  2. 在mybatis核心配置文件中配置拦截器插件

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
                <!--指定数据库方言,可无需配置,默认识别具体的数据库管理系统-->
                <property name="helperDialect" value="mysql"/>
                <!--
                pageSizeZero:默认值为 false,当该参数设置为 true 时,
                如果 pageSize=0 或者 RowBounds.limit = 0
                就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。
                -->
                <property name="pageSizeZero" value="true"/>
                <!--
                reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,
                pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),
                会查询最后一页。默认false 时,直接根据参数进行查询。
                -->
                <property name="reasonable" value="true"/>
        </plugin>
    </plugins>

  3. 执行分页

    @Test
    public void selectAll() {
        //执行分页(参数一:当前页,参数二:每页数据条数)
        PageHelper.startPage(2,3);
    ​
        List<User> users = mapper.selectAll();
        
        //如果需要更详细分页信息,则可以基于集合创建PageInfo对象
        PageInfo<User> pageInfo = new PageInfo<>(users);
        
        //创建分页详细信息对象时指定导航页码数(只显示某几页:默认值为8)
        //PageInfo<User> pageInfo = new PageInfo<>(users,5);
        
        users.forEach(System.out::println);
        assertNotNull(users);
    }

    PageInfo类似之前所自己封装PageModel类

3.6. 环境配置

在日常软件开发中通常存在很多不同“环境”,常见的环境包含:开发环境生产环境

  • 开发环境:项目在本地开发测试中,并未正式上线运行的环境

  • 测试环境:项目处于测试阶段时(一般为测试人员的测试环境)

  • 生产环境:项目版本已发布,并部署到对外的应用服务器为普通用户使用(正式上线运行)

<!--环境配置-->
<environments default="product">
    <environment id="development">
        <transactionManager type="JDBC"/>
        <!-- 数据源配置 -->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
​
    <!--配置另一个环境-->
    <environment id="product">
        <!--配置事务管理器-->
        <transactionManager type="JDBC"/>
        <!--数据源配置-->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="jdbc:mysql://127.0.0.1:3306/mydb?serverTimezone=UTC"/>
            <property name="username" value="${jdbc.user}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>

切换环境只需要通过设置environments标签中的default指向即可,defualt值为environmentid属性值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值