MyBatis系列(一)——MyBatis的介绍和CRUD

前言

MyBatis是一个第三方开发的一款优秀的持久层框架,它不仅解决了原始JDBC操作数据库的繁琐步骤,而且还提供了自定义 SQL、存储过程以及高级映射等功能来简化我们的开发。当前MyBatis已经成为了许多项目的选择使用的持久层框架,作为一个java开发人员,掌握和清楚Mybatis的使用和原理是很有必要的。本篇文章将作为MyBatis系列的首篇,来介绍MyBatis的产生背景和基本的CRUD操作,希望能给各位读者一个参考。

想要了解更多MyBaits系列文章,可以从下面的传送门阅读:

MyBatis系列(二)——MyBatis的动态代理和映射文件动态配置


一、MyBatis的介绍

(一)MyBatis的产生背景

我们在前面的文章中曾经提到,java虽然给数据库厂商提供了操作数据库的接口,但原始的JDBC操作步骤还是十分的繁琐,需要我们手动写很多代码,这就引出了JDBC Template工具的出现来简化我们的开发,MyBatis也是在这种背景下产生的产物,但它比JDBC TemplateDBUtils等工具类不同的是,它支持的功能更加强大、更丰富,所以也成为了许多项目持久层框架的选择。

口说无凭,下面我们就以常规的查询操作,来看一下原始的JDBC操作是什么样的吧
/**
 *   该类用于演示使用JDBC原始API操作数据库案例
 */
public class JdbcForSqlTest {

    public static User getUserById() throws Exception{
        // 注册mysql驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 获取jdbc连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","root.");
        // 传入sql语句,获取预处理对象
        PreparedStatement preparedStatement = connection.prepareStatement("select * from user where uid = ?");
        // 传入参数
        preparedStatement.setString(1,"1");
        // 执行sql
        ResultSet resultSet = preparedStatement.executeQuery();
        // 将resultSet 拆分为具体的对象
        User user = new User();
        while (resultSet.next()){
            user.setUid(resultSet.getInt("uid"));
            user.setUsername(resultSet.getString("username"));
            user.setPassword(resultSet.getString("password"));
        }
        // 释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
        return user;
    }

    public static void main(String[] args) throws Exception {
        System.out.println(getUserById());
    }
}

我们从上面的代码中可以发现,原始的JDBC操作有着以下三个缺点:
1. 没有线程池的概念,每次执行sql都要获取和销毁数据库连接资源,浪费系统资源
2. sql语句没有实现解耦合,比如数据库的配置和sql语句都耦合在了代码上面,一旦配置或者sql语句需要变动,就要改java代码,而且也不方便复用。
3. 操作繁琐 查询操作时,需要手动将结果集中的数据手动封装到实体中。插入操作时,需要手动将实体的数据设置到sql语句的占位符位置.

那么,针对这些问题,MyBatis提出了以下的解决方案:
  • 使用数据库连接池初始化连接资源
  • 将sql语句和数据库配置抽取到xml配置文件中
  • 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射
(二)MyBaits的简单演示Demo

下面我们来简单演示一下同样的需求,使用MyBatis是怎么样解决的:

1. 引入MyBatis依赖

如果已经引入了驱动包的话这里就只需要引入MyBatis坐标就行

<!-- 引入mysql驱动依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>
        <!-- 引入mybatis依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
2. 将数据库配置抽取为jdbc.properties文件
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root
3. 创建UserMapper.xml文件

UserMapper.xml用于存放我们抽取出来的sql语句

<?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="getUserById" parameterType="java.lang.Integer" resultType="com.qiqv.pojo.User">
        select * from user where uid = #{id}
    </select>
</mapper>

这里需要注意的有两点:

  1. mapper标签中的namespace属性,表示这个文件主要封装了哪个实体类的sql语句,我们需要保证每个mapper.xml文件的这个属性唯一。
  2. select 标签表示该标签下的是select查询语句
4. 创建MyBatis核心配置文件sqlMapConfig.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>

    <!-- 获取jdbc.properties -->
    <properties resource="jdbc.properties" ></properties>

    <!-- 配置源环境 -->
     <environments default="developement">
        <environment id="developement">
            <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/qiqv/mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>

在这个配置文件中,我们引入了jdbc.properties文件和UserMapper.xml,同时在enviroment标签中配置了事务管理器为JDBC,使用MyBatis的数据库连接池。

5. 编写实际的sql代码
public class MyBatisForSqlTest {

    public static User getUserById() throws IOException {
        // 将核心配置文件转为流对象
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 创建sqlSessionFactoryBuild对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        // 获取连接对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 执行sql语句
        List<User> user = sqlSession.selectList("userMapper.getUserById", 1);
       // 关闭资源
        sqlSession.close();
        return user.get(0);
    }

    public static void main(String[] args) throws IOException {
        System.out.println(getUserById());
    }
}

我们可以看到,使用MyBatis之后,我们的结果集和参数的数据封装、sql和数据库的配置参数、数据库连接池的问题就都得到了解决。看起来似乎我们做多了很多步骤,但实际上当MyBaits的框架搭好后,我们后面开发起来就不需要这么麻烦了。

二、MyBatis的配置文件概述

(一)映射文件

在第一节中,我们使用了UserMapper.xml来封装我们的sql语句,下面我们就对这个配置文件来做一下基本的介绍吧。除开xml文件的约束头之外,我们日常开发中基本上都是在mapper标签中添加和修改各式的sql语句,根据不同类型的sql语句,对应也有着selectupdateinsertdelete标签使用。
同时,虽然映射文件没有强制的命名规范,但我们一般还是会按照 pojo对象名 + Mapper.xml的命名规则来定义映射文件

(二)核心配置文件
1. MyBatis核心配置文件层级关系
2. MyBatis常用配置解析
2.1 environments标签

MyBaits允许我们在environments标签中定义多套环境,比如开发环境、测试环境等,我们可以根据需要修改选择运行环境。

其中,事务管理器(transactionManager)类型有两种:
JDBC:这个配置就是直接使用了JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
MANAGED:这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接,然而一些容器并不希望这样,因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。

其中,数据源(dataSource)类型有三种:
UNPOOLED:这个数据源的实现只是每次被请求时打开和关闭连接。(相当于没用连接池)
POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来。
JNDI:这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用。

2.2 mapper标签

该标签的作用是加载映射文件的,加载方式有如下几种:

  • 使用相对于类路径的资源引用,例如:<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  • 使用完全限定资源定位符(URL),例如:<mapper url="file:///var/mappers/AuthorMapper.xml"/>
  • 使用映射器接口实现类的完全限定类名,例如:<mapper class="org.mybatis.builder.AuthorMapper"/>
  • 将包内的映射器接口实现全部注册为映射器,例如:<package name="org.mybatis.builder"/>

我们一般使用第一种和第四种方式比较多

2.3 Properties标签

实际开发中,习惯将数据源的配置信息单独抽取成一个properties文件,该标签可以加载额外配置的properties文件


2.4 typeAlias标签

见名知义,typeAlias标签的作用是设置别名。我们在第一节的例子的映射文件中,使用了resultTypeparamterType两个属性来定义结果类型和返回值类型,我们需要填入对应类的全路径包名


但每次都要写类的全路径十分麻烦,别名的存在就帮我们解决了这个问题
MyBaits中,已经帮我们定义好了一些常用的别名

别名 数据类型
string String
long Long
int lnteger
double Double
boolean Boolean
... ...

我们也可以在核心配置文件中定义我们自己的别名

  <!--  配置别名 -->
    <typeAliases >
        <typeAlias type="com.qiqv.pojo.User" alias="user"></typeAlias>
     </typeAliases>

这样我们原先映射文件中的sql标签就可以使用别名了


三、MyBatis的CRUD操作

(一)新增操作

映射文件中新增sql语句

   <insert id="insertUser" parameterType="user">
        insert into user values (#{uid},#{username},#{password})
    </insert>

java代码如下:

public class UserDaoImpl implements UserDao {
    public boolean addUser(User user) throws IOException {
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession();
        int result = sqlSession.insert("userMapper.insertUser",user);
        System.out.println(result);
        sqlSession.commit();
        sqlSession.close();
        return result>0;
    }
}

这里需要注意的是,如果没有开启自动提交事务的话,需要手动执行commit方法

(二)修改操作

映射文件中新增sql语句

    <update id="updateUser" parameterType="user">
        update user set username = #{username} where uid=#{uid};
    </update>

java代码如下:

public class UserDaoImpl implements UserDao {
    public boolean updateUser(User user)throws Exception  {
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession();
        int result = sqlSession.update("userMapper.updateUser",user);
        sqlSession.commit();
        sqlSession.close();
        return result>0;
    }
}
(三)删除操作

映射文件中新增sql语句

    <delete id="delUser" parameterType="int">
        delete from user where uid=#{id};
    </delete>

java代码如下:

public class UserDaoImpl implements UserDao {
    public boolean deleteUser(Integer uid)throws Exception  {
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession();
        int result = sqlSession.delete("userMapper.delUser",uid);
        sqlSession.commit();
        sqlSession.close();
        return result>0;
    }
}
(四)查询操作

映射文件中新增sql语句

   <select id="getAllUser" resultType="user">
       select * from user
   </select>

java代码如下:

public class UserDaoImpl implements UserDao {
      public List<User> getAllUser() throws Exception {
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession = factory.openSession();
        List<User> users = sqlSession.selectList("userMapper.getAllUser");
        System.out.println(users);
        sqlSession.close();
        return users;
    }
}

至此,本篇文章中我们对MyBatis的入门介绍已经结束了,实际上MyBaits的入门操作并不难。我们在开发过程中遇到的问题往往也不仅仅是简单的单表操作,MyBaits的还有许多方法来帮助我们更好地解决DAO层的问题,想要了解更多可以参考本系列的其他文章。

posted @ 2021-04-01 15:32  moutory  阅读(5)  评论(0编辑  收藏  举报  来源