初识Mybatis

69 阅读4分钟

文章目录


Mybatis

1. 前言

Java中对于数据库的相关操作我们可以使用JDBC来完成,例如:此时我们想要实现根据用户名和密码来实现登录验证的功能,代码如下:

import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;

public class LoginDemo {
    public static void main(String[] args) throws SQLException {
        Scanner sc = new Scanner(System.in);
        System.out.println("please input your username...");
        String username = sc.nextLine();
        System.out.println("please input your password...");
        String password = sc.nextLine();
        boolean b = safeLogin(username, password);
        String message = b == true ? "welcome..." : "please input correct username and password!";
        System.out.println(message);
    }
	
	// 登录
    public static boolean safeLogin(String username, String password) throws SQLException {
        if (username == null || password == null){
            return false;
        }

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet res = null;
        String sql = "SELECT * FROM account WHERE username = ? AND password = ?";

        try{
            conn = getConnectionByProperties();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, username);
            pstmt.setString(2, password);
            res = pstmt.executeQuery();
            return res.next();

        } catch (Exception e){
            e.printStackTrace();
        } finally {
            close(res, pstmt, conn);
        }
        return false;
    }
		
	// 使用配置文件获取数据库连接
    public static Connection getConnectionByProperties(){
        try {
            Class<Main> cls = Main.class;
            Properties pro = new Properties();
            InputStream is = cls.getClassLoader().getResourceAsStream("JDBC/jdbc.properties");
            pro.load(is);

            String driver = pro.getProperty("driver");
            String url = pro.getProperty("url");
            String username = pro.getProperty("username");
            String password = pro.getProperty("password");

            Class.forName(driver);
            return DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 关闭连接
    public static void close(ResultSet resultSet, PreparedStatement pst, Connection connection) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (pst != null) {
            try {
                pst.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

上面的例子使用了JDBC来获取连接,并使用PreparedStatement来执行SQL语句,并通过ResultSet获取结果。当数据库相关的操作较多时,通常可以使用数据库连接池来减少因获取和释放连接而产生的开销。但是这样的方式具有如下的不足:

  • SQL语句在代码中硬编码,造成代码不易维护,以及程序的更新
  • 使用PreparedStatement像占位符传参存在硬编码,而SQL语句中的where条件通常变化很大,修改SQL语句就需要修改代码,不易维护
  • 对结果集的硬编码,SQL语句的改变会导致解析代码发生改变,不易维护

2. 概念

MyBatis 是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录

3. 功能架构

Mybatis功能架构分为三层:

  • API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理
  • 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作
  • 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑

3. 环境搭建

  • 创建Maven工程,并在pom.xml中添加Mybatis、MySQL等相关的依赖

    <?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>MybatisLearn</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <dependencies>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.4</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.20</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
        </dependencies>
    </project>
    

    如果出现Dependency xxxxx not found可以更新一下Maven Repositories。详细路径为FIle - setting - Build,Execution, Deployment - Repositories,点击Update按钮更新即可,可能速度有点慢。

    在这里插入图片描述
    假设此时的account表如下所示:

mysql> select * from account;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | Forlogen | 100      |
|  2 | Kobe     | 110      |
+----+----------+----------+
2 rows in set (0.02 sec)

表中只有int型的id、String型的username和String型的password。然后编写account表对应的实体类,类中的成员变量名和accoutn表的列名要完全一致

import java.io.Serializable;

public class Account implements Serializable {
    private int id;
    private String username;
    private String password;

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "DAO.Account{" +
                "id=" + id +
                ", name='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

使用Mybatis要编写持久层接口,这里定义为UserMapper,接口中的方法是我们想要执行的SQL语句对应的方法:

import DAO.Account;
import java.util.List;

public interface UserMapper {
    List<Account> findAllUserInfo();
}

然后编写对应的持久层接口映射文件UserMapper.xml,这里要注意两点:

  • XML文件的名字和接口的名字要完全相同
  • XML文件的路径和接口的路径要完全相同,UserMapper.xml在resources包下,UserMapper.java在main包下
<?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="mapper.UserMapper">
    <select id="findAllUserInfo" resultType="DAO.Account">
        select * from account
    </select>
</mapper>
  • namespace:持久层接口的全限定接口名
  • id:接口中想要实现的方法
  • resultType:SQL语句执行结果的包装类
  • <select></select>中写要执行的SQL语句

为了连接到数据库,我们还需要编写关于数据库的配置文件,通常命名为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">
<!-- mybatis 主配置文件 -->
<configuration>
    <!-- 配置环境 -->
    <environments default="mysql">
        <!-- 配置mysql的环境-->
        <environment id="mysql">
            <!-- 配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <!-- 配置连接数据库的4个基本信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/sql_store?serverTimezone=GMT"/>
                <property name="username" value="root"/>
                <property name="password" value="1234"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

<property></property>中分别写入连接数据库的信息,它和JDBC中的是一样的。最后编写测试类:

import mapper.UserMapper;
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.InputStream;
import java.util.List;

public class Demo {
    public static void main(String[] args) throws Exception {
        //1.读取配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory的构建者对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //3.使用构建者创建工厂对象
        SqlSessionFactory factory = builder.build(in);
        //4.使用SqlSessionFactory生产SqlSession对象
        SqlSession session = factory.openSession();
        //5.使用SqlSession创建dao接口的代理对象
        UserMapper account = session.getMapper(UserMapper.class);
        //6.使用代理对象执行查询所有方法
        List<Account> users = account.findAllUserInfo();
        for(Account user : users) {
            System.out.println(user);
        }
        //7.释放资源
        session.close();
        in.close();
    }
}