Mybatis基本应用

1. 框架

  软件开发常用的是架构是三层架构,包括持久层,业务层和表现层

  • 持久层:主要完成与数据库相关的操作,CRUD
  • 业务层:主要根据功能需求完成业务逻辑的定义与实现
  • 表现层: 主要完成与用户的交互
  • 表现出调研业务层,业务层调用持久层,利用javabean实体对象传递数据

 

 

  框架封装了冗余且重用率低的代码,利用反射与动态代理机制,实现代码通用性。

  • 常见的框架类型
    • 持久层框架用于解决数据持久化的框架: mybatis,hibernate,spring jdbc等
    • 全栈框架能在各层都给出解决方法:spring
    • 表现层框架专注于解决与用户交互的框架:spring mvc, struts2等
    • SSM=spring mvc+ spring + mybatis
    • SSH=spring jdbc + spring +hibernate

2.mybatis

mybatis是一个基于ORM的半自动轻量级持久层框架,对jdbc的操作数据库的过程进行封装。

  • 原始jdbc存在的问题
    • 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能 --- 使用数据库连接池初始化连接资源
    • SQL语句在代码中硬编码,代码不移维护 --- 将SQL语句写到配置文件xml中
    • 查询操作时,需要手动将结果集封装到实体中 --- 利用反射内省等底层技术自动将实体与表进行属性和字段的自动映射
  • ORM 对象关系映射
    • O 对象模型Object  javabean对象
    • R relational 关系型数据库的数据结构
    • M mapping映射 从数据库到对象模型的映射,通过xml实现
    • ORM跟踪实体变化,并将实体的变化映射翻译成SQL脚本执行到数据库中去

 

3. mybatis快速入门

  • 创建数据库及实体表
CREATE DATABASE `mybatis_db`;

USE `mybatis_db`;
CREATE TABLE `user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(32) NOT NULL COMMENT '用户名称',
`birthday` DATETIME DEFAULT NULL COMMENT '生日',
`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
-- insert....
INSERT INTO `user`(`id`,`username`,`birthday`,`sex`,`address`) VALUES (1,'子
慕','2020-11-11 00:00:00','','北京海淀'),(2,'应颠','2020-12-12 00:00:00','','北
京海淀');
  • 创建maven工具,导入依赖,包括mysql驱动,mybatis,junits测试单元
<?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>org.example</groupId>
    <artifactId>mybatis_quickstart</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--指定编码和版本-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.encoding>UTF-8</maven.compiler.encoding>
        <java.version>1.11</java.version>
        <maven.compiler.source>1.11</maven.compiler.source>
        <maven.compiler.target>1.11</maven.compiler.target>
    </properties>

    <dependencies>
       <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
            <scope>runtime</scope>
        </dependency>

<!-- mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>

<!-- junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
    </build>


</project>
  • 编写实体类表
package com.rf.domain;

import java.util.Date;

public class User {
//    `id` INT(11) NOT NULL AUTO_INCREMENT,
    private  int id;
//`username` VARCHAR(32) NOT NULL COMMENT '用户名称',
    private String username;
//`birthday` DATETIME DEFAULT NULL COMMENT '生日',
    private Date birthday;
//`sex` CHAR(1) DEFAULT NULL COMMENT '性别',
    private String sex;
//`address` VARCHAR(256) DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`)
    private String address;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
  •  编写mapper映射配置文件,在java.com.rf.mapper下
<?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="UserMapper">
<!-- 查询所有-->
    <select id="findAll" resultType="com.rf.domain.User">
        select * from user
    </select>

<!-- 插入操作-->
    <insert id="saveUser" parameterType="com.rf.domain.User">
        insert into user (username,birthday,sex,address) values  (#{username},#{birthday},#{sex},#{address})
    </insert>

<!-- 修改操作-->
<update id="updateUser" parameterType="com.rf.domain.User">
    update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
</update>
    
<!--  删除操作-->
    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>

</mapper>
  • 编写sqlMapConfig.xml核心配置文件,只有一份,在resource文件下
<?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="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis_db"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
                
            </dataSource>
        </environment>
    </environments>

<!--    映射文件配置-->
    <mappers>
<!--  单个文件映射-->
        <mapper resource="com/rf/mapper/UserMapper.xml"></mapper> <!-- 批量映射--> <!-- <package name="com/rf/domain"/>--> </mappers> </configuration>
  •  测试代码
import com.rf.domain.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.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

public class UserTest {
    private SqlSession sqlSession;

    @Test
    public void testfindAll() throws IOException {
        //1.加载核心配置文件import org.apache.ibatis.io.Resources;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory 工厂对象
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //3.获取会话对象
        SqlSession sqlSession = sessionFactory.openSession();
        //4.执行SQL语句
        List<User> users = sqlSession.selectList("UserMapper.findAll");
        for (User user : users) {
            System.out.println(user);
        }
        //5.释放资源
        sqlSession.close();
    }

    @Test
    public void testsaveUser() throws IOException {
        //1.加载核心配置文件import org.apache.ibatis.io.Resources;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory 工厂对象
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //3.获取会话对象,这里未设置自动提交
        SqlSession sqlSession = sessionFactory.openSession();
        //4.执行SQL语句
        User user = new User();
        user.setUsername("xiaoming");
        user.setBirthday(new Date());
        user.setSex("男");
        user.setAddress("北京朝阳");
        sqlSession.insert("UserMapper.saveUser", user);
        // 一定手动提交
        sqlSession.commit();

        //5.释放资源
        sqlSession.close();
    }

    @Test
    public void testupdateUser() throws IOException {
        //1.加载核心配置文件import org.apache.ibatis.io.Resources;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory 工厂对象
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //3.获取会话对象
        SqlSession sqlSession = sessionFactory.openSession();
        //4.执行SQL语句
        //4.执行SQL语句
        User user = new User();
        user.setId(3);
        user.setUsername("lucy");
        user.setBirthday(new Date());
        user.setSex("女");
        user.setAddress("北京");
        sqlSession.update("UserMapper.updateUser",user);
        sqlSession.commit();
        //5.释放资源
        sqlSession.close();
    }

    @Test
    public void testdeleteUser() throws IOException {
        //1.加载核心配置文件import org.apache.ibatis.io.Resources;
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory 工厂对象
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        //3.获取会话对象
        SqlSession sqlSession = sessionFactory.openSession();
        //4.执行SQL语句
        List<User> users = sqlSession.selectList("UserMapper.deleteUser", 4);
        sqlSession.commit();
        //5.释放资源
        sqlSession.close();
    }
}
  •  注意事项
    • 进行增删改操作时要提交事务commit,否则在创建会话对象时就设置自动提交为true
    • SQL语句中使用#{字符串}方式引用传递的单个参数
    • 在映射文件中使用parameterType设置插入的数据类型,使用resultType设置返回的封装类型

4. 核心配置文件概述

  • SqlMapConfig.xml文件层级关系,设置时参照该顺序

 

 

  •  environments 数据库环境的配置,支持多环境配置
    • 事务管理器transactionManager
      • JDBC 直接使用了JDBC的提交和回滚设置,依赖于从数据源得到的连接来管理事务作业域
      • MANAGED 让容器接管事务的生命周期
    • 数据源dataSource
      • POOLED 利用数据连接池
      • UNPOOLED 不使用数据连接池,每次都单独创建并关闭连接
      • JNDI 为了能在如EJB或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置JNDI 上下文的数据源引用
  • properties 将数据源的配置单独抽取为一个properties文件,加载外在配置
jdbc.driver= com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_db
jdbc.username=root
jdbs.password=123456
<?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"></properties>
<!--    运行环境配置-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
                
            </dataSource>
        </environment>
    </environments>

<!--    映射文件配置-->
    <mappers>
<!--  单个文件映射-->
        <mapper resource="com/rf/mapper/UserMapper.xml"></mapper>

<!--  批量映射-->
<!--        <package name="com/rf/domain"/>-->
    </mappers>
    
</configuration>
  • typeAliases起别名,简化映射文件java类型
<!-- 查询所有-->
    <select id="findAll" resultType="user">
        select * from user
    </select>
<!--  起别名-->
    <typeAliases>
        <typeAlias type="com.rf.domain.User" alias="user"></typeAlias>
    </typeAliases>
  • mappers 映射文件配置
1. 使用相对于类路径的资源引用,例如:
<mapper resource="org/mybatis/builder/userMapper.xml"/>
2. 使用完全限定资源定位符(URL),例如:
<mapper url="file:///var/mappers/userMapper.xml"/>3. 使用映射器接口实现类的完全限定类名,例如:
<mapper class="org.mybatis.builder.userMapper"/>
4. 将包内的映射器接口实现全部注册为映射器,例如:
<package name="org.mybatis.builder"/>

5. mybatis API 引用

  SqlSession工厂构建器SqlSessionFactoryBuilder,通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象。Resources 工具类,这个类在 org.apache.ibatis.io 包中。Resources 类帮助你从类路径下、文件系统或一个 web URL 中加载资源文件

SqlSession工厂对象SqlSessionFactory 创建SqlSession 实例

SqlSession会话对象进行CRUD

  • mybatis基本原理
  • mybatis动态代理
    • 传统dao模式需要编写dao接口和实现类,实现类中存在mybatis模板重复,实现类调用方法时xml文件中的sql statement硬编码到java代码中
    • 采用mybatis的基于代理接口方式实现持久层的开发,只需要编写Mapper接口,mybatis会动态生成实现类的对象

 

  • Mapper.xml映射文件中的namespacemapper接口的全限定名相同
  • Mapper接口方法名和Mapper.xml映射文件中定义的每个statementid相同
  • Mapper接口方法的输入参数类型和mapper.xml映射文件中定义的每个sqlparameterType的类型相同
  • Mapper接口方法的输出参数类型和mapper.xml映射文件中定义的每个sqlresultType的类型相同
  • 内部执行原理:mapper是一个代理对象,是有MapperProxy代理产生的,MapperProxy使用invoke方法,最终调用了mapperMethod.execute(SqlSession,args),而该方法execute最终执行的是SqlSession的CRUE操作。

 

posted @ 2021-07-10 16:51  forever_fate  阅读(140)  评论(0)    收藏  举报