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 对象。
调用 SqlSessionFactory 的 openSession() 方法获取一个 SqlSession 对象。
SqlSession 对象不是线程安全的,其作用域应该是方法作用域,并且用完即关闭,不应该在方法间传递共享。
SqlSessionFactory sqlSessionFactory = MyBatisUtils.getSqlSessionFactory();
try(SqlSession sqlSession = sqlSessionFactory.openSession(true)) // 自动提交事务
{
// 执行CRUD
}
最后,调用 SqlSession 的 getMapper() 方法,获取到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);
}
}