【MyBatis从入门到入土】1 - MyBatis入门

MyBtis从入门到入土

0 基础

学习MyBtis之前,需要对一下技术有一定的了解:

  1. Java基础
  2. Mysql
  3. JDBC:Java Database Connectivity
  4. Maven
  5. Junit

1 简介

1.1 什么是Mybatis

MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records.
MyBaits是第一个支持自定义SQL、存储过程和高级映射的类持久层框架。MyBtis消除了几乎所有的JDBC代码、手动设置参数值和查询结果集。MyBatis可以使用简单的XML和注解来配置和映射原始信息,将接口和Java的POJOs(Plain Old Java Object,普通的Java对象 )映射成数据库中的记录。

  • 由来
    百度百科对MyBatis词条的解释:

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)
当前,最新版本是MyBatis 3.5.5 ,其发布时间是2020年6月4日。

   <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
</dependency>

1.2 持久化

持久化:程序数据再持久状态和瞬时状态转化的机制。
举个栗子:
在程序运行的时候,我们有时候希望保存我们的程序数据,比如用户、密码等信息数据,这个时候,我们就需要将这些程序数据固定下来。
我们知道,程序运行时数据是保存在内存中的。内存速度快,但价格高昂,且断电易失,而硬盘速度慢,但价格低廉,即使断电数据也不会丢失,取长补短,那我们就可以将内存中的程序数据保存到硬盘中,在需要的时候再取出来。存取数据的过程就叫持久化。

1.3 持久层

  • 完成持久化工作的代码块
  • 分层是为了让职责更加明确

1.4 为什么需要MyBatis

  • 好用,流行框架
  • 简化JDBC
  • 方便数据持久化
    另外贴上百度百科对MyBatis特点的总结
  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解耦:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。

2 第一个MyBatis程序

2.1 搭建环境

创建数据库mybatis和表user,插入测试数据

mysql> CREATE DATABASE mybatis;
Query OK, 1 row affected (0.06 sec)

mysql> USE mybatis
Database changed
mysql> CREATE TABLE user(
    -> id INT NOT NULL PRIMARY KEY,
    -> name VARCHAR(30) DEFAULT NULL,
    -> pwd VARCHAR(30) DEFAULT NULL
    -> )ENGINE=InnoDB;
Query OK, 0 rows affected (0.13 sec)

mysql> INSERT INTO user(id,name,pwd)
    -> VALUES
    -> (1,'狂神','123456'),
    -> (2,'张三','123456'),
    -> (3,'李四','123456');
Query OK, 3 rows affected (0.02 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT id,name,pwd FROM user;
+----+--------+--------+
| id | name   | pwd    |
+----+--------+--------+
|  1 | 狂神   | 123456 |
|  2 | 张三   | 123456 |
|  3 | 李四   | 123456 |
+----+--------+--------+
3 rows in set (0.01 sec)
  1. 新建一个maven工程
    在这里插入图片描述在这里插入图片描述
  2. 删除src:时当前工程成为其他模块的父工程
  3. 在pom.xml中导入依赖
    <!-- 导入依赖 -->
    <dependencies>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>

        <!-- Mybatis依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.5</version>
        </dependency>

        <!-- JUnit依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

2.2 创建一个新模块Modul

  1. 创建一个新模块
    在这里插入图片描述在这里插入图片描述2. 在src/main/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核心配置文件 -->
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!-- xml中需要用 &amp; 转义表示 &  -->                
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis&amp;useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="mysql"/>
            </dataSource>
        </environment>
    </environments>
</configuration>
  1. 编写一个工具类,用来获取sqlSession对象
    在这里插入图片描述
package com.cap.utils;
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;


    //获取sqlSessionFactory
    static{
        InputStream inputStream = null;
        try {
            String resource = "mybatis-config.xml";
            inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /*
    Now that you have a SqlSessionFactory, as the name suggests, you can acquire an instance of SqlSession.
     The SqlSession contains absolutely every method needed to execute SQL commands against the database.
     */

    public static SqlSession getSqlSession(){
        return  sqlSessionFactory.openSession();
    }
    
}

2.3 编写代码

  1. 实体类User
package com.cap.pojo;

/**
 * 实体类
 * 这里提一下ORM思想(Object Relational Mapping对象关系映射)
 *  - 一个实体类对应一个表
 *  - 实体类的一个对象对应表中的一行记录
 *  - 对象中的一个成员变量对应一行记录中的一列属性
 * @author cap
 * @create 2020.06.29.16:25
 */
public class User {
    private int id;
    private String name;
    private String pwd;

    public User() {
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }
	//...省略Getter和Setter方法
}
  1. DAO接口

以前我们都是称之为DAO(Data Access Object数据访问对象),但在MyBatis中我们都是用xml配置文件来映射到我们需要的SQL语句,所以在之后MyBatis的使用中,我们更习惯用Mapping来作为对DAO的替代命名。

package com.cap.dao;
/**
 * @author cap
 * @create 2020.06.29.17:00
 */
public interface UserDao {
    List<User> getUserList();
}

  1. 接口实现类

由原来的DaoUserImpl实现类改为现在的一个UserMapping.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">
<!-- namespace对应一个DAO/Mapping接口 -->
<mapper namespace="com.cap.dao.UserDao">
    <!-- SELECT语句, -->
    <select id="getUserList" resultType="com.cap.pojo.User">
        SELECT * FROM mybatis.user;
    </select>

</mapper>

2.4 测试

一般我们会在test/java包下建立一个对应的测试类
在这里插入图片描述

public class UserDaoTest {
    @Test
    public void test(){
        //第一步:获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //方式一:getMapper
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        List<User> userList = userDao.getUserList();

        for(User user : userList){
            System.out.println(user);
        }

        //关闭sqlSession
        sqlSession.close();

    }
}
  • 解决报错1
    说明一下,以下展现的报错信息省略了其他无相关的信息
java.lang.ExceptionInInitializerError
	....
### Error building SqlSession.
### Cause: org.apache.ibatis.builder.BuilderException: Error creating document instance.  Cause: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence....

可以看到,这个原因主要是因为编码集的问题,将mybatis-config.xml和UserMapping.xml的编码集UTF-8改为UTF8
在这里插入图片描述

  • 解决报错2:配置文件没有注册
org.apache.ibatis.binding.BindingException: Type interface com.cap.dao.UserDao is not known to the MapperRegistry.

可以看到,这里说到了对于MapperRegistry来说,它还不认识UserDao接口,其实这是因为我们在mybatis-config.xml添加配置信息的时候,我们除了配置了数据库连接的相关信息,其实还需要配置对于DAO层中的UserMapping.xml,这样MyBatis才能从mybatis-config.xml中去读取到UserMapping中相关的SQL语句和UserDao接口
在这里插入图片描述在mybatis-config.xml中新添加mappers标签来配置UserMapping.xml路径

    <mappers>
        <mapper resource="com/cap/dao/UserMapping.xml"/>
    </mappers>
  • 报错3:Maven资源导出问题
    <!-- 在build中配置resources,来防止我们资源导出失败的问题 -->
   <build>
       <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>

在这里插入图片描述
另一种方式,这种方法了解一下就可,因为他有两个弊端,一是容易出现字面量错误,二是有转型安全问题

    @Test
    public void test2(){
        //第一步:获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //方式二:
        List<User> userList = sqlSession.selectList("com.cap.dao.UserDao.getUserList");
        /*
        这种方式不推荐,原因有二
        一是容易出现字面量错误
        二是原本List<Object>现在需要强转
         */


        for(User user : userList){
            System.out.println(user);
        }

        //关闭sqlSession
        sqlSession.close();
    }

3 CRUD

为了命名方便,我们将项目原来的UserDao接口改名为UserMapping

3.1 SELECT

  1. 在接口UserMapping增加一个新方法getUserById()
    /**
     * <p>根据id查询用户</p>
     * @param id
     * @return
     */
    User getUserById(int id);
  1. 在配置文件UserMapping.xml编写SQL语句
<mapper namespace="com.cap.dao.UserMapping">    
    <select id="getUserById" resultType="com.cap.pojo.User" parameterType="int">
        SELECT * FROM mybatis.user
        WHERE id = #{id};
    </select>
</mapper>
  • id:对应的接口方法名
  • parameterType:参数类型
  • resultType:返回类型,注意这里使用全限定名
    -#():指定方法形参名
  1. 编写测试方法
    /**
     * 测试查询操作
     */
    @Test
    public void test3(){
        //第一步:获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        //第二步:执行,获取结果集
        UserMapping mapper = sqlSession.getMapper(UserMapping.class);
        User user = mapper.getUserById(2);

        System.out.println(user);

        sqlSession.close();
    }
    /**OUTPUT
    User{id=2, name='张三', pwd='123456'}
    */

3.2 INSERT

  1. 在接口增加一个新方法addUser()
    /**
     * <p>插入一个新用户</p>
      * @param user
     */
    int addUser(User user);
  1. 在配置文件UserMapping.xml编写SQL语句
<mapper namespace="com.cap.dao.UserMapping">    
    <!-- User中的成员变量可以直接用
    (MyBatis反射直接取到类的成员变量,
    这样一来就绕开了Getter、Setter,更加方便)-->
    <insert id="addUser"  parameterType="com.cap.pojo.User" >
        INSERT INTO mybatis.user(id,name,pwd)
        VALUES(#{id},#{name},#{pwd});
    </insert>
</mapper>    

注意这里#()可以直接使用User中的属性,这样一来就绕开了Getter、Setter,更加方便

  1. 编写测试类
    /**
     * 测试插入操作
     */
    @Test
    public void test4(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();

        UserMapping mapper = sqlSession.getMapper(UserMapping.class);
        //返回的是受影响的行数,大于0说明插入成功
        int resultInt = mapper.addUser(new User(5,"李白","123456"));

        if(resultInt > 0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }

        //增删改需要提交事务
        sqlSession.commit();

        sqlSession.close();
    }
    /**OUTPUT
    插入成功
    */

注意这里需要手动提交事务

对于更新UPDATE、删除DELETE操作来说,步骤都是一样的,先在接口声明变量,然后配置SQL,最后编写测试方法,这里就不再赘述。另外如果接口方法有多个形参,那么就不能使用parameterType,方法见博客Mybatis (ParameterType) 如何传递多个不同类型的参数(注意这篇博客提到的的第一种方法已经不能再使用01,使用arg0arg1或者使用param1param2

3.3 模糊查询

接口编写模糊查询方法

    List<User> getUserLike(String name);

方式一:在UserMapping.xml配置文件中编写SQL语句,附带通配符

    <!-- 模糊查询 -->
    <select id="getUserLike" resultType="com.cap.pojo.User" parameterType="String">
        SELECT * FROM mybatis.user
        WHERE name LIKE "%"#{name}"%";
    </select>
        List<User> userList = mapper.getUserLike("狂");
        for(User user : userList){
            System.out.println(user);
        }
        /**OUTPUT
        User{id=1, name='狂神', pwd='123456'}
		User{id=6, name='狂铁', pwd='123456'}
		*/

方式二:调用方法时传入的参数附带通配符

    <!-- 模糊查询 -->
    <select id="getUserLike" resultType="com.cap.pojo.User" parameterType="String">
        SELECT * FROM mybatis.user
        WHERE name LIKE "%"#{name}"%";
    </select>
        List<User> userList = mapper.getUserLike("%狂%");
        for(User user : userList){
            System.out.println(user);
        }
        /**OUTPUT
        User{id=1, name='狂神', pwd='123456'}
		User{id=6, name='狂铁', pwd='123456'}
		*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值