mybatis入门案例

88 阅读3分钟

官方文档:mybatis.org/mybatis-3/z…

mybatis时Java中的持久层框架,通过配置(XML或注解),可以将数据库中的记录映射为Java Bean对象,省去了JDBC中手动创建对象的过程。

准备数据库表

CREATE DATABASE IF NOT EXISTS test;

CREATE TABLE `user` (
  `id` tinyint(4) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `username` varchar(64) DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

使用步骤

1.创建maven项目,并添加相关依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.25</version>
</dependency>

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
</dependency>

2.创建mybatis核心配置文件

mybatis核心配置中,必备的数据源以及事务相关的配置

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>
    <properties>
        <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://192.168.2.21:3306/test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

3.定义表对应的实体类

对于实体类中的字段,基本类型的字段推荐使用其包装类型,因为字段的值可能为null。

me.lyp.entity.User

import lombok.*;

@Data
@NoArgsConstructor
@RequiredArgsConstructor
public class User
{
    private int id;
    @NonNull
    private String username;
    @NonNull
    private String password;
}

4.定义Mapper接口

me.lyp.mapper.UserMapper

import java.util.List;
import me.lyp.entity.User;

public interface UserMapper
{
    int insertOne(User user);
    
    int deleteOneById(Integer id);
    
    int updateOne(User user);
    
    User selectOneById(Integer id);
}

5.创建xml映射文件

mapper映射文件中,根标签上的namespace属性用于声明命名空间,结合insert,delete,update,select标签上的id属性,可以唯一定位一个mapper接口方法。

src/main/resources/me/lyp/mapper/UserMapper.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">
<mapper namespace="me.lyp.mapper.UserMapper">

    <insert id="insert" parameterType="me.lyp.entity.User">
        INSERT INTO user (username, password)
        VALUES (#{username}, #{password});
    </insert>

    <delete id="deleteById" parameterType="int">
        DELETE FROM user WHERE id = #{id};
    </delete>

    <update id="update" parameterType="me.lyp.entity.User">
        UPDATE user
        SET username = #{username},
            password = #{password}
        WHERE id = #{id};
    </update>

    <select id="selectById" parameterType="int" resultType="me.lyp.entity.User">
        SELECT * FROM user WHERE id = #{id};
    </select>
</mapper>

xml映射文件需要在mybatis核心配置文件中进行引入

<configuration>
     <!-- ... -->
    <mappers>
        <mapper resource="me/lyp/mapper/UserMapper.xml"/>
    </mappers>
 <configuration>

6.执行CRUD操作

首先,需要获取 SqlSessionFactory 对象,这个对象用于创建 SqlSession 对象,并且在应用运行期间应该只存在一个。

所以,最佳实践是使用单例模式创建并获取它。

me.lyp.utils.MyBatisUtils

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MyBatisUtils {
    private static SqlSessionFactory INSTANCE;

    static {
        try {
            InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            INSTANCE = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSessionFactory getSqlSessionFactory() {
        return INSTANCE;
    }
}

然后,获取 SqlSession 对象。

调用 SqlSessionFactoryopenSession() 方法获取一个 SqlSession 对象。

SqlSession 对象不是线程安全的,其作用域应该是方法作用域,并且用完即关闭,不应该在方法间传递共享。

SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
try(SqlSession sqlSession = sqlSessionFactory.openSession(true)) // 自动提交事务
{
    // 执行CRUD
}

最后,调用 SqlSessiongetMapper() 方法,获取到mapper接口类型的对象,执行CRUD操作。

mapper接口对象应该和 SqlSession 对象一样,其作用域应该是方法作用域,用完即丢弃(JVM进行垃圾回收)

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

CRUD测试代码如下

me/lyp/AppTest.java

import me.lyp.entity.User;
import me.lyp.mapper.UserMapper;
import me.lyp.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

public class AppTest {

    @Test
    public void test_insert(){
        SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)){
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);

            User user = new User("admin", "admin123");
            int insertRows = mapper.insert(user);
            Assertions.assertEquals(1, insertRows);
        }
    }

    @Test
    public void test_select(){
        SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);

            User user = mapper.selectById(1);
            Assertions.assertEquals("admin", user.getUsername());
        }
    }
    
    @Test
    public void test_update(){
        SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);

            User user = mapper.selectById(1);
            user.setPassword("admin321");
            int updateRows = mapper.update(user);
            Assertions.assertEquals(1, updateRows);
        }
    }
    
    @Test
    public void test_delete(){
        SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
        try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);

            int deleteRows = mapper.deleteById(1);
            Assertions.assertEquals(1, deleteRows);
        }
    }
}

另外,Mapper接口不是必须的。

实际上,mybatis内部通过mapper接口对象执行CRUD的操作,是通过 SqlSession 实现的。

可以不用定义mapper接口,直接使用 SqlSession 对象执行xml映射文件中定义的CRUD SQL。

例如,直接在 UserMapper.xml 中定义如下sql

<mapper namespace="me.lyp.mapper.UserMapper">
    <!-- 省略其它sql -->

    <select id="exists" parameterType="int" resultType="boolean">
        SELECT count(1) > 0 FROM user WHERE id = #{id};
    </select>
</mapper>

在java中,通过 SqlSession 执行它

@Test
public void test_exists(){
    SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
    try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
        Object exists = sqlSession.selectOne("me.lyp.mapper.UserMapper.exists", 1);
        Assertions.assertTrue((Boolean)exists);
    }
}