Java MyBatis 入门教程

一、MyBatis

MyBatis 是一个基于 java 的持久层ORM( Object Relational Mapping,对象关系映射)

框架,内部封装了 jdbc,开发者只需要关注 sql 语句 本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。

MyBatis 通过 xml 或注解,两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的 动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

1.不使用 MyBatis的代码

(1)注册驱动

(2)获取连接

(3)获取数据库操作对象

(4)执行SQL语句

(5)处理查询结果集

(6)释放资源

这些导致

(1)代码比较多,开发效率低

(2)需要关注 Connection ,Statement, 9ResultSet 对象创建和销毁

(3)对 ResultSet 查询的结果,需要自己封装为 List

(4)重复的代码比较多些

(5)业务代码和数据库的操作混在一起。

java 复制代码
 String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/mydb";
        String user = "root";
        String pwd = "123456";
 
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
 
        try {
            //1、注册驱动(连接的数据库)
            Class.forName(driver);
 
            //2、获取连接
            conn = DriverManager.getConnection(url,user,pwd);
 
            //3、获取数据库操作对象(专门执行sql语句的对象)
            stmt = conn.createStatement();
 
            //4、执行SQL语句(DQL DML....)
            String sql = "select empno,empname as name,sal from emp2 where empno=7369";
            rs = stmt.executeQuery(sql);
 
            //5、处理查询结果集(只有当第四步执行的是select语句的时候,才有处理查询结果集)
            while (rs.next()){
                /*
                (1)下标取值;下标从 1 开始
                */
                String empno = rs.getString(1);
                String empname = rs.getString(2);
                String sal = rs.getString(3);
                System.out.println(empno + " " + empname + " " + sal);
 
                /*
                (2)数据类型取值
                */
                int empno1 = rs.getInt(1);
                String empname1 = rs.getString(2);
                Double sal1 = rs.getDouble(3);
                System.out.println(empno1 + " " + empname1 + " " + sal1);
 
                /*
                (3)字段名取值
                */
                String empno2 = rs.getString("empno");
                //如果执行的SQL语句中有别名,需要使用别名字段取值
                String empname2 = rs.getString("name");
                String sal2 = rs.getString("sal");
                System.out.println(empno2 + " " + empname2 + " " + sal2);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            //6、释放资源;从小到大关闭
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

2.使用MyBatis的代码

mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)

(1)sql mapper:sql映射

把数据库表中的一行数据 映射为 一个java对象

一行数据可以看做是一个java对象;操作这个对象,就相当于操作表中的数据

(2)Data Access Objects(DAOs):数据访问 , 对数据库执行增删改查

MyBatis框架

【1】提供了创建和销毁、关闭Connection ,Statement, ResultSet等对象能力

【2】提供了执行sql语句的能力

【3】提供了循环sql, 把sql的结果转为java对象, List集合的能力

二、MyBatis入门SqlSession

首先以SqlSession的方式使用mybatis框架

首先我们先设置一下maven的本地仓库

1.新建一个数据库表user

sql 复制代码
CREATE TABLE `user` (
  `user_id` int(10) NOT NULL COMMENT '用户名ID',
  `user_name` varchar(100) DEFAULT NULL COMMENT '用户名',
  `email` varchar(80) DEFAULT NULL COMMENT '用户邮箱',
  `age` int(5) DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.配置pom.xml

XML 复制代码
<?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>maven-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <!--    <modules>-->
    <!--        <module>untitled</module>-->
    <!--    </modules>-->

    <properties>
        <!-- 源码编译 jdk 版本 -->
        <maven.compiler.source>1.8</maven.compiler.source>
        <!-- 运行代码的 jdk 版本 -->
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- 项目构建使用的编码,避免中文乱码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <!--项目引入插件所需要的额外依赖 -->
    <dependencies>
        <!--参见dependencies/dependency元素 -->
        <!-- 单元测试依赖 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.junit.jupiter</groupId>-->
<!--            <artifactId>junit-jupiter</artifactId>-->
<!--            <version>RELEASE</version>-->
<!--            <scope>compile</scope>-->
<!--        </dependency>-->
<!--        json转换依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory><!--所在的目录-->
                <includes><!--包括目录下的.properties,.xml 文件都会扫描到-->
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <!-- filtering 选项 false 不启用过滤器, *.property 已经起到过滤的作用了 -->
                <filtering>false</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>16</source>
                    <target>16</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3.创建java实体类User

java 复制代码
package com.example.domain;
 
public class User {
    private int userId;//  对应数据表User user_id
    private String userName;//  对应数据表User user_name
    private String email;  // 对应数据表User email
    private int age;// 对应数据表User age
 
    public int getUserId() {
        return userId;
    }
 
    public void setUserId(int userId) {
        this.userId = userId;
    }
 
    public String getUserName() {
        return userName;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public String getEmail() {
        return email;
    }
 
    public void setEmail(String email) {
        this.email = email;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
}

4、创建持久层的dao接口

UserDao.java

用于 定义操作数据库的方法

java 复制代码
package org.example.dao;

import org.example.domain.User;

import java.util.List;

/**
 * 用户的持久层接口
 * 继承该接口的类,实现接口中的方法,就可以实现对user表的增删改查
 */
public interface UserDao {
    /**
     * 查询user列表
     * @param user 单个user用户     [入参是user对象]
     * @return user的list
     */
    List<User> selectUserList(User user);  // 方法名和mapper.xml中的id值一致

    /**
     * 插入user
     * @param user
     * @return
     */
    int insertUser(User user);// 方法名和mapper.xml中的id值一致
}

UserDao接口定义了两个方法,继承了该接口的类,要实现这两个接口方法。

上面两个接口中的方法,入参是一个实体类User对象,即之前步骤3 定义一行表数据对应一个java对象,操作该对象就是操作数据表这行数据。

5、映射文件

创建一个mybatis使用的配置文件 SQL映射文件

编写SQL语句,一般一个表对应一个SQL映射文件,这个文件就是xml文件

sql映射文件(sql mapper)

编写SQL语句,mybatis负责执行这些SQL语句

UserDao.xml

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">

<!--
    sql映射文件(sql mapper):编写SQL语句,mybatis负责执行这些SQL语句
    1、指定约束文件
    <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
     mybatis-3-mapper.dtd:约束文件名称
    2、约束文件作用:限制,检查当前文件中出现的标签,属性必须符合mybatis的要求
    3、<mapper>:当前文件根标签(必须的)
       namespace:命名空间(唯一值,自定义字符串;要求使用dao接口的全限定名称)
       全限定类名:就是类名全称,带包路径的用点隔开,如: java.lang.String
          即全限定名 = 包名 + 类型
       非限定类名也叫短名,就是我们平时说的类名,不带包的,如:String
    4、数据库增删改查特定标签
       <select>:查询,select语句
       <update>:更新,update语句
       <insert>:插入,insert语句
       <delete>:删除,delete语句
-->

<mapper namespace="com.example.dao.UserDao">

    <!--
        <select>标签:查询操作
        id:执行SQL语法的唯一标识,mybatis会根据这个id的值来找到要执行的SQL语句
            可以自定义,一般要求使用接口中的方法名称
        resultType:表示结果类型,SQL语句执行后得到ResultSet结果集,遍历这个结果集得到的Java对象类型
            值写Java对象的全限定名称
    -->
    <select id="selectUserList" resultType="com.example.domain.User">
        select user_Id,user_Name,email,age
        from user
        order by user_Id asc
    </select>

    <!--插入操作,字段名和Java实体类中字段保持一致-->
    <insert id="insertUser">
        insert into user values(#{userId},#{userName},#{email},#{age})
    </insert>

</mapper>

6、创建mybatis的主配置文件

主配置文件提供了数据库的连接信息 和 SQL映射文件的位置 信息,一个项目一个主配置文件。

mybatis-config.xml

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的主配置文件:主要定义了数据库的配置信息,SQL映射文件的位置
            1、约束文件
                <!DOCTYPE configuration
                    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
                    "http://mybatis.org/dtd/mybatis-3-config.dtd">
                mybatis-3-config.dtd:约束文件名称
            2、configuration:根标签
        -->
<configuration>

<!-- settings:mybatis全局行为 -->
<settings>
    <!-- 设置mybatis输出日志 -->
    <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>

<!--
    环境配置:数据库的连接信息
        default:必须和某个environment的id值一样
        告诉mybatis使用哪个数据库的连接信息(访问哪个数据库)
-->
<environments default="development">

    <!--
        environment:一个数据库的配置,环境
        id:一个唯一值(可自定义,表示环境的名称)
     -->
    <environment id="development">
        <!--
            transactionManaer:mybatis的事务类型
                type:JDBC(表示使用JDBC中的Connection对象的commit,rollback做事务处理)
        -->
        <transactionManager type="JDBC"/>
        <!--
            dataSource:表示数据源,连接数据库的
                type:表述数据源的类型,POOLED表示使用连接池
        -->
        <dataSource type="POOLED">
            <!--
               driver, user, username, password 是固定的,不能自定义。
            -->
            <!-- 数据库驱动类名 -->
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <!-- 连接数据库的URL字符串 -->
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test"/>
            <!-- 访问数据库的用户名 -->
            <property name="username" value="root"/>
            <!-- 访问数据库的密码 -->
            <property name="password" value="lyc123456"/>
        </dataSource>
    </environment>

    <!--表示线上的数据库,是项目真实使用的库-->
    <environment id="online">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis_test"/>
            <property name="username" value="root"/>
            <property name="password" value="lyc123456"/>
        </dataSource>
    </environment>

</environments>

<!-- sql mapper(SQL映射文件)的位置 -->
<mappers>
    <!--
        一个mapper标签指定一个文件的位置
            从类路径开始的路径信息(target/classes)类路径
    -->
    <mapper resource="org/mybatis/example/UserDao.xml"/>
</mappers>
</configuration>

每个表都会配置一个mapper 即xml文件。

7、创建使用mybatis测试类

通过mybatis访问数据库

java 复制代码
package org.example;

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.example.domain.User;
import org.example.utils.MyBatisUtil;
import org.junit.jupiter.api.Test;

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

public class TestMyBatis {
    /**
     * 查询user列表
     */
    @Test
    public void testSelectUserList(){
        try {
            //访问mybatis读取user数据
            //1、定义mybatis主配置文件名称,从类路径的根开始(target/clasess)
            String config = "mybatis-config.xml";
            //2、读取config表示的文件
            InputStream in = Resources.getResourceAsStream(config);
            //3、创建SqlSessionFactoryBuilder对象
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            //4、创建SqlSessionFactory对象
            SqlSessionFactory factory = builder.build(in);
            //5、获取SqlSession对象,从SqlSessionFactory中获取SqlSession(非自动提交事务,如果增删改需要手动提交事务)
            SqlSession sqlSession = factory.openSession();
            //6、指定要执行的SQL语句标识;sql映射文件中的 namespace + "." + 标签的id值
            String sqlId = "org.example.dao.UserDao.selectUserList";
            //7、执行sql语句,通过sqlId找到语句
            List<User> userList = sqlSession.selectList(sqlId);
            //8、输出结果
            for (User user:userList){
                System.out.println("查询用户="+user);
            }
            //9、关闭SQLSession对象
            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询user列表
     */
    @Test
    public void testMyBatisUtil(){
        try {
            SqlSession sqlSession = MyBatisUtil.getSqlSession();
            String sqlId = "com.example.dao.UserDao.selectUserList";
            //7、执行sql语句,通过sqlId找到语句
            List<User> userList = sqlSession.selectList(sqlId);
            //8、输出结果
            for (User user:userList){
                System.out.println("查询用户="+user);
            }
            //9、关闭SQLSession对象
            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 插入
     */
    @Test
    public void testInsertUser(){
        SqlSession sqlSession = null;
        try {
            sqlSession = MyBatisUtil.getSqlSession();
            String sqlId = "com.mycompany.dao.UserDao.insertUser";
            //7、执行sql语句,通过sqlId找到语句
            User user = new User();
            user.setUserId(5);
            user.setUserName("zhangfei");
            user.setEmail("[email protected]");
            user.setAge(16);
            int nums = sqlSession.insert(sqlId,user);

            //mybatis默认不是自动提交事务的, 所以在insert ,update ,delete后要手工提交事务
            sqlSession.commit();

            System.out.println("更新用户条数="+nums);

            //9、关闭SQLSession对象
            sqlSession.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

7.将SqlSession提取为工具类MyBatisUtil

复制代码
MyBatisUtil.java
java 复制代码
package org.example.utils;

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.IOException;
import java.io.InputStream;

public class MyBatisUtil {
    public MyBatisUtil() {
    }

    public static SqlSession getSqlSession() throws IOException {
        String config = "mybatis-config.xml";
        InputStream ins = Resources.getResourceAsStream(config);
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(ins);
        SqlSession sqlSession = factory.openSession();
        return sqlSession;
    }
}

后续使用sqlSession,就实例化这个工具类MyBatisUtils类

(1)Resources

mybatis中的一个类, 负责读取主配置文件

java 复制代码
//    1、定义mybatis主配置文件名称,从类路径的根开始(target/clasess)
String config = "mybatis-config.xml";
 
//    2、读取config表示的文件
InputStream in = Resources.getResourceAsStream(config);

(2)SqlSessionFactoryBuilder

创建SqlSessionFactory对象

java 复制代码
//    3、创建SqlSessionFactoryBuilder对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
 
//    4、创建SqlSessionFactory对象
SqlSessionFactory factory = builder.build(in);

完整目录

10、常见报错问题

(1)找不到mybatis-config.xml文件或者对应的dao以及SQL映射文件

三种解决方案:

【1】maven clean一下,然后compile一下,会重新生成target目录

【2】Rebuild Project,再重新运行,就会在target目录下出现mybatis-config.xml文件

【3】以上两种方式不行,直接手动将src/resources/mybatis-config.xml文件拷贝至target/classes目录下

(2)dao接口的 方法 和 dao.xml映射文件中的 id 要保持一致(重点)

(3)数据库表中的列名,要和Java实体类中的字段,dao.xml映射文件的属性字段保持一致(重点)

11、 junit : 单元测试

junit:单元测试, 一个工具类库,做测试方法使用的。单元:指定的是方法, 一个类中有很多方法,一个方法称为单元

使用单元测试

(1)需要加入junit依赖

XML 复制代码
<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
</dependency>

(2)创建测试类

src/test/java目录中创建类

(3)创建测试方法

【1】public 方法

【2】没有返回值 void

【3】方法名称自定义,建议名称是test + 测试方法名称

【4】方法没有参数

【5】方法的上面加入 @Test ,方法可以单独执行;不用使用main方法

相关推荐
Sunlight_77712 分钟前
第五章 SQLite数据库:1、SQLite 基础语法及使用案例
java·linux·服务器·jvm·数据库·tcp/ip·sqlite
嘉嘉king29 分钟前
Mysql联表查询
数据库
镜舟科技1 小时前
NoSQL 与 NewSQL 全面对比:如何选择适合你的数据库方案?
数据库·starrocks·nosql·newsql·技术架构·实时数据分析
TDengine (老段)1 小时前
TDengine 语言连接器(Node.js)
大数据·c语言·数据库·物联网·node.js·时序数据库·tdengine
Sunlight_7772 小时前
第五章 SQLite数据库:3、SQLite 常用语法及使用案例
jvm·数据库·sqlite
数据库砖家2 小时前
YashanDB|虚拟内存高出实际内存十几G?原因不只是“占用大”这么简单
数据库
郭源潮13 小时前
《MySQL:MySQL表结构的基本操作》
数据库·mysql
火龙谷3 小时前
【hive】Hive对数据库,对表的操作(一)
数据库·hive·hadoop
西门吹雪@1323 小时前
redis 配置日志和数据存储位置
数据库·redis·缓存