初识MyBatis
-
-
- 1. MyBatis 简介
- 2. MyBatis 快速入门
- 3. 使用 MyBatis 的注意事项
- 4. 自定义接口
-
1. MyBatis 简介
什么是 MyBatis?
-
MyBatis 是 Apache 的一个开源项目 iBatis,2010 年这个项目由 Apache Software Foundation 迁移到了 Google Code,由谷歌公司负责维护,并且改名为 MyBatis;2013 年 11 月迁移到 Github。
-
MyBatis 是一个企业级数据持久化的开发框架,支持三种语言的实现,如Java、.NET 和 Ruby,可以理解为一个底层是 JDBC 的封装框架。
目前常用的企业级数据持久化框架:Hibernate、MyBatis、Spring Data JPA、MyBatis Plus
ORM:Object Relationship Mapping,即对象关系映射,把面向对象的 JavaBean 和关系型数据表进行字段与属性之间的逐一映射。
MyBatis 是目前主流的 ORM 框架,MyBatis 消除了几乎所有的 JDBC 代码和参数的手动配置以及对结果集的遍历与封装,可以使用简单的 XML 或注解用于配置和原始映射,通过接口将 JavaBean 映射成数据库中的记录。
MyBatis 的优点:
- 极大地简化了底层 JDBC 代码的开发;
- 简单易于上手、具有很强的灵活性;
- SQL 写入 XML 配置文件,实现和 Java 代码的解耦合;
- 支持动态 SQL,可以根据具体业务灵活实现需求;
MyBatis 的缺点:
- 相比于 Hibernate,开发者需要完成更多的工作,比如:定义 SQL、完成结果集与实体类的匹配;
- 要求开发人员具备一定的 SQL 编写能力;
- 数据库移植性较差,因为 SQL 依赖底层的数据库,如果要进行数据库迁移,部分 SQL 需要重新编写。
2. MyBatis 快速入门
Step1:首先创建 Maven 工程,在工程目录下的 pom.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>com.training</groupId>
<artifactId>mavenPro</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--添加 jar 包的依赖-->
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!--MySQL-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
Step2:创建数据表与对应的实体类 User
create table test.user
(
id int auto_increment primary key,
name varchar(225) null,
score double null
);
package com.training.entity;
import lombok.Data;
//使用这个插件后,默认生成属性的Getter与Setter方法以及无参构造方法
@Data
public class User {
private Integer id;
private String name;
private Double score;
}
Step3:创建 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>
<!--数据源-->
<environments default="dev">
<!--可以配置多个环境-->
<environment id="dev">
<!--配置JDBC事务管理-->
<transactionManager type="JDBC"></transactionManager>
<!-- POOLED配置JDBC数据库连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
</dataSource>
</environment>
</environments>
</configuration>
4、调用API完成操作(使用原生接口)
MyBatis 框架需要开发者自定义 SQL 语句,写在 XxxMapper.xml
文件中。实际开发中,会为每个实体类创建对应的 XxxMapper.xml
,定义管理该对象数据的 SQL。
创建 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="com.training.mapper.UserMapper">
<select id="get" parameterType="int" resultType="com.training.entity.User">
select * from user where id=#{id}
</select>
<insert id="increase" parameterType="com.training.entity.User">
insert into user (id,name,score) values (#{id},#{name},#{score});
</insert>
</mapper>
- namespace 通常为所在包 + 文件名的形式;
- insert 标签表示执行添加操作;
- select 标签表示执行查询操作;
- update 标签表示执行更新操作;
- delete 标签表示执行删除操作
- id 是实际调用 MyBatis 方法时需要用到的参数;
- parameterType 是调用对应方法时参数的数据类型;
- resultType 是调用方法返回结果集的类型;
在全局配置文件 config.xml 中注册 UserMapper.xml
<!-- 注册UserMapper.xml -->
<mappers>
<mapper resource="com/training/mapper/UserMapper.xml"></mapper>
</mappers>
调用原生接口执行 SQL,获取结果集
import com.training.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class Test {
public static void main(String[] args) {
//加载MyBatis配置信息
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
//构建SQLSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new
SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
//获取SqlSession
SqlSession sqlSession = factory.openSession();
//查询操作
String statement1 = "com.training.mapper.UserMapper.get";
User user = (User)sqlSession.selectOne(statement1, 1);
System.out.println(user);
//增加操作
String statement2 = "com.training.mapper.UserMapper.increase";
User user1 = new User(4,"赵六",89.5);
sqlSession.insert(statement2,user1);
sqlSession.commit();
}
}
如果控制台报错:Cause: java.io.IOException: Could not find resource com/training/mapper/UserMapper.xml
,需要在 pom.xml 中增加以下配置信息,以便让src/main/java路径下的 XML 文件可以被读取到。
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
修改之后,程序正常运行。控制台的输出结果如下:
3. 使用 MyBatis 的注意事项
-
Mapper.xml 必须要在 config.xml (全局环境配置)中进行注册,才可以使用,否则会抛出异常;
<!-- 注册UserMapper.xml --> <mappers> <mapper resource="com/training/mapper/UserMapper.xml"></mapper> </mappers>
-
statement 执行字符串必须是 Mapper 接口的命名空间 + 方法 id;
-
需要修改 pom.xml,让 src/main/java 路径下的 XML 文件可以被读取到,默认只能读取到 src/main/resources 下的配置信息,所以需要手动设置,否则会抛出如下异常;
<build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> </resources> </build>
4. 自定义接口
通过 Mapper 代理实现自定义接口,解决原生接口所带来的弊端,由于原生方式每次调用业务方法,都需要拼接字符串 String statement = "com.training.mapper.UserMapper.increase"
,使得调用方法比较繁琐,且易于出错。因此,在实际项目开发中,通常推荐使用自定义接口:
- 自定义接口,定义相关的业务方法;
- 编写与方法对应的 Mapper.xml;
Step1:自定义接口
package com.training.mapper;
import com.training.entity.User;
import java.util.List;
public interface UserMapper {
public User findById(Integer id);
public List<User> findAll();
public int add(User user);
public int deleteById(Integer id);
public int update(User user);
}
Step2:创建接口对应的 UserMapper.xml,定义接口方法对应的 SQL 语句
MyBatis 框架会根据规则(接口与XML配置)自动创建接口实现类的代理对象
规则:statement 标签可根据 SQL 执行的业务选择 insert、delete、update、select
- UserMapper.xml 中 namespace 为接口的全类名;
- UserMapper.xml 中 statement 的 id 为接口中对应的方法名;
- UserMapper.xml 中 statement 的 parameterType 和接口中定义方法的参数类型一致;
- UserMapper.xml 中 statement 的 resultType 和接口中对应方法的返回值类型一致;
<?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="com.training.mapper.UserMapper">
<insert id="add" parameterType="com.training.entity.User">
insert into user(name,score) values(#{name},#{score})
</insert>
<delete id="deleteById" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<update id="update" parameterType="com.training.entity.User">
update user set name=#{name},score=#{score} where id=#{id}
</update>
<select id="findById" parameterType="java.lang.Integer" resultType="com.training.entity.User">
select * from user where id=#{id};
</select>
<select id="findAll" resultType="com.training.entity.User">
select * from user;
</select>
</mapper>
Step3:在全局配置文件 config.xml 中注册 UserMapper.xml
<mappers>
<mapper resource="com/training/mapper/UserMapper.xml"></mapper>
</mappers>
Step4:调用接口的代理对象完成相关的业务操作
package com.training.test;
import com.training.entity.User;
import com.training.mapper.UserMapper;
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 Test {
public static void main(String[] args) {
//加载MyBatis配置信息
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
//构建SQLSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new
SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
//获取SqlSession
SqlSession sqlSession = factory.openSession();
//获取实现接口的代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//查询id为2的用户对象
System.out.println(mapper.findById(2));
//查询全部对象
List<User> users = mapper.findAll();
System.out.println(users);
//增加用户对象
User user1 = new User();
user1.setName("小明");
user1.setScore(86.5);
int add = mapper.add(user1);
System.out.println(add);
//增删改需要提交事务,查询不需要
sqlSession.commit();
}
}
注意:修改对象时,先通过查询方法查找指定 id 的用户对象,再调用该用户的 set 方法对字段信息进行修改,最后将修改后的用户对象传入更新方法完成修改操作。
如果数据表的字段名与实体类的属性名不同时,则需要在 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="com.training.mapper.UserMapper">
<insert id="add" parameterType="com.training.entity.User">
insert into user(name,score) values(#{stuName},#{stuScore})
</insert>
<delete id="deleteById" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
<update id="update" parameterType="com.training.entity.User">
update user set name=#{stuName},score=#{stuScore} where id=#{stuId}
</update>
<resultMap id="userMap" type="com.training.entity.User">
<id property="stuId" column="id"></id>
<result property="stuName" column="name"></result>
<result property="stuScore" column="score"></result>
</resultMap>
<select id="findById" parameterType="java.lang.Integer" resultMap="userMap">
select * from user where id=#{id};
</select>
<select id="findAll" resultMap="userMap">
select * from user;
</select>
</mapper>
注意:
- 如果数据表字段名与 JavaBean 属性名不一致时,执行查询业务获取结果集时,要对字段名与属性名进行逐一映射;
- parameterType 参数是全类名时,比如:
com.training.entity.User
,传入的#{stuName}
是对象的属性名,底层会通过反射机制调用 get 方法,即会调用getStuName()
方法完成数据的注入,如果误写成数据表的字段#{name}
,则会报错找不到getName()
方法。
测试类 Test
public class Test {
public static void main(String[] args) {
//加载MyBatis配置信息
InputStream inputStream = Test.class.getClassLoader().getResourceAsStream("config.xml");
//构建SQLSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new
SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
//获取SqlSession
SqlSession sqlSession = factory.openSession();
//获取实现接口的代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//查询id为2的用户对象
System.out.println(mapper.findById(2));
//修改用户信息
User user1 = mapper.findById(2);
user1.setStuName("李力");
user1.setStuScore(96.5);
int update = mapper.update(user1);
System.out.println(update);
//删除用户
int delete = mapper.deleteById(5);
System.out.println(delete);
//查询全部对象
List<User> users = mapper.findAll();
System.out.println(users);
}
}
控制台的打印结果如下: