Mybatis是一个用Java语言编写的持久层框架,它使用ORM实现了对结果集的封装。
ORM(Object Relational Mapping):对象关系映射。简单来说,就是把数据库表和实体类及实体类的属性对应起来,让开发者操作实体类就能实现操作数据库表,它封装了JDBC操作的很多细节,使开发者只需要关注SQL语句本身,而无需关注注册驱动、创建连接等复杂过程。
Mybatis中文网
Mybatis中有两种开发方式:
一般最常用的方式是基于XML的方式进行开发,而基于XML方式开发也有两种方式:
CREATE DATABASE IF NOT EXISTS db_mybatis
DEFAULT CHARACTER SET utf8;
USE db_mybatis;
CREATE TABLE `tb_user` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `tb_user`(`name`) VALUES('Bob');
INSERT INTO `tb_user`(`name`) VALUES('Tom');
INSERT INTO `tb_user`(`name`) VALUES('Jack');
INSERT INTO `tb_user`(`name`) VALUES('John');
pom.xml
<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.0modelVersion>
<groupId>comgroupId>
<artifactId>mybatisartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.18version>
dependency>
dependencies>
project>
mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/db_mybatis?serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="mappers/userMapper.xml"/>
mappers>
configuration>
UserEntity.java
package com.mybatis.entity;
/**
* @author honey
* @date 2023-07-26 15:29:38
*/
public class UserEntity {
private Integer id;
private String name;
@Override
public String toString() {
return "UserEntity{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
userMapper.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="userMapper">
<select id="listUser" resultType="com.mybatis.entity.UserEntity">
select * from tb_user
select>
mapper>
MybatisTest01.java
package com.mybatis.test;
import com.mybatis.entity.UserEntity;
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;
import java.util.List;
/**
* @author honey
* @date 2023-07-26 15:26:48
*/
public class MybatisTest01 {
public static void main(String[] args) throws IOException {
// 1.读取加载mybatis-config.xml(数据源、mybatis等配置)
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3.根据mapper(namespace="userMapper" + id="listUser")执行sql语句,并将查询到的数据映射成对象(orm)
List<UserEntity> list = sqlSession.selectList("userMapper.listUser", UserEntity.class);
System.out.println(list);
sqlSession.close();
}
}
下面这些情况是没有问题的
第三种情况如下所示(SQL语句查询的结果与构造方法中的参数能够成功映射):
SQL语句
实体类
异常情况:
解决方案:在实体类中再额外添加一个无参构造方法。
相较于原生方式开发,mapper代理开发的优势:不依赖于字符串的字面值,减少了硬编码
原生方式开发:
List<UserEntity> list = sqlSession.selectList("com.mybatis.mapper.UserMapper.listUser", UserEntity.class);
mapper代理开发:
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<UserEntity> list = mapper.listUser();
userMapper.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mybatis.mapper.UserMapper">
<select id="listUser" resultType="com.mybatis.entity.UserEntity">
select * from tb_user
select>
mapper>
UserMapper.java
package com.mybatis.mapper;
import com.mybatis.entity.UserEntity;
import java.util.List;
/**
* @author honey
* @date 2023-07-26 21:04:23
*/
public interface UserMapper {
/**
* 查询用户列表
*
* @return List
*/
List<UserEntity> listUser();
}
MybatisTest02.java
package com.mybatis.test;
import com.mybatis.entity.UserEntity;
import com.mybatis.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.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author honey
* @date 2023-07-26 21:15:48
*/
public class MybatisTest02 {
public static void main(String[] args) throws IOException {
// 1.读取加载mybatis-config.xml(数据源、mybatis等配置)
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3.根据mapper(namespace="UserMapper全限定名" + id="listUser")执行sql语句,并将查询到的数据映射成对象(orm)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<UserEntity> list = mapper.listUser();
System.out.println(list);
sqlSession.close();
}
}
SQL映射文件中namespace未设置为接口全限定名会导致程序在执行的时候找不到namespace=接口全限定名所对应的SQL映射文件。
解决方法:
优点:去除XML配置,提高了开发效率;
缺点:SQL语句植入Java代码,如果需要修改SQL语句必须修改源码,会导致维护成本增加,基于XML方式维护性更强;
pom.xml
<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.0modelVersion>
<groupId>comgroupId>
<artifactId>mybatis-annotationartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.4.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.18version>
dependency>
dependencies>
project>
UserEntity.java
package com.mybatis.entity;
/**
* @author honey
* @date 2023-07-26 15:29:38
*/
public class UserEntity {
private Integer id;
private String name;
@Override
public String toString() {
return "UserEntity{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
UserMapper.java
package com.mybatis.mapper;
import com.mybatis.entity.UserEntity;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* @author honey
* @date 2023-07-26 21:04:23
*/
public interface UserMapper {
/**
* 基于注解方式查询用户列表
*
* @return List
*/
@Select("select * from tb_user")
List<UserEntity> listUserByAnnotation();
}
mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/db_mybatis?serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="admin"/>
dataSource>
environment>
environments>
<mappers>
<mapper class="com.mybatis.mapper.UserMapper"/>
mappers>
configuration>
MybatisTest01.java
package com.mybatis.test;
import com.mybatis.entity.UserEntity;
import com.mybatis.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.IOException;
import java.io.InputStream;
import java.util.List;
/**
* @author honey
* @date 2023-07-26 21:15:48
*/
public class MybatisTest01 {
public static void main(String[] args) throws IOException {
// 1.读取加载mybatis-config.xml(数据源、mybatis等配置)
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 2.获取sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 3.根据mapper(namespace="com.mybatis.mapper.UserMapper" + id="listUser")执行sql语句,并将查询到的数据映射成对象(orm)
List<UserEntity> list = sqlSession.selectList("com.mybatis.mapper.UserMapper.listUserByAnnotation", UserEntity.class);
System.out.println(list);
// 3.根据mapper(namespace="UserMapper全限定名" + id="listUser")执行sql语句,并将查询到的数据映射成对象(orm)
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<UserEntity> list2 = mapper.listUserByAnnotation();
System.out.println(list2);
sqlSession.close();
}
}
使用以下两种注册mapper的方式存在着很大的弊端
<mapper resource="mappers/userMapper.xml"/>
<mapper class="com.mybatis.mapper.UserMapper"/>
弊端:在每次创建mapper接口或者mapper.xml文件时,都需要在mybatis-config.xml中新增配置。
企业级开发时,通常会使用扫包的方式注册mapper
<package name="com.mybatis.mapper"/>
在基于XML方式-mapper代理开发的基础上进行优化:
注意:虽然文件名称需要保持一致,但是文件名称的大小写不敏感,也就是说命名为userMapper.xml或者usermapper.xml都是可行的。
在基于注解方式的基础上进行优化:只需要修改mybatis-config.xml,使用扫包方式注册mapper即可。(请参考上述第二个步骤)
注册方式 | 注册对象 | 限制条件 |
---|---|---|
resource | 注册单个映射文件 | 直接加载映射文件,没有限制映射文件的包名结构和文件名称,非常灵活,不易出错 |
class | 注册单个mapper接口 | SQL映射文件需要与mapper接口的包名结构和文件名称保持一致 |
package | 注册包名下所有的mapper接口 | SQL映射文件需要与mapper接口的包名结构和文件名称保持一致 |