Mybatis环境搭建与使用
- Mybatis介绍
- Mybatis环境搭建与使用
- 基于XML方式-原生方式开发
- 创建数据库表
- 项目准备
- 项目结构
- 项目代码
- 实体类中添加有参构造方法产生的问题
- 基于XML方式-mapper代理开发
- 项目准备
- 项目结构
- 项目代码
- SQL映射文件中namespace未设置为接口全限定名产生的问题
- 基于注解方式
- 项目准备
- 项目结构
- 项目代码
- 企业级规范开发
- 基于XML方式-mapper代理开发(优化版)
- 基于注解方式(优化版)
- 注册映射文件(resource、class、package三者的区别)
Mybatis介绍
Mybatis是一个用Java语言编写的持久层框架,它使用ORM实现了对结果集的封装。
ORM(Object Relational Mapping):对象关系映射。简单来说,就是把数据库表和实体类及实体类的属性对应起来,让开发者操作实体类就能实现操作数据库表,它封装了JDBC操作的很多细节,使开发者只需要关注SQL语句本身,而无需关注注册驱动、创建连接等复杂过程。
Mybatis中文网
Mybatis环境搭建与使用
Mybatis中有两种开发方式:
- 基于注解方式;
- 基于XML方式;
一般最常用的方式是基于XML的方式进行开发,而基于XML方式开发也有两种方式:
- 原生方式开发
- mapper代理开发
基于XML方式-原生方式开发
- 创建数据库表;
- 引入mybatis相关依赖;
- 配置数据源、mybatis等相关配置(mybatis-config.xml);
- 定义Java对象,对象的成员属性与数据库表中的字段名称对应;
- 定义mapper.xml文件,存放需要执行的SQL语句,每个表对应一个mapper;
- 调用mybatis框架中的api执行SQL语句并获取结果集;
创建数据库表
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
<?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</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
</dependencies>
</project>
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="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
<?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="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语句
实体类
异常情况:
- SQL语句保持不变,将实体类调整为下述情况则会报错
- 实体类保持不变,将SQL语句调整为下述情况则会报错
解决方案:在实体类中再额外添加一个无参构造方法。
基于XML方式-mapper代理开发
相较于原生方式开发,mapper代理开发的优势:不依赖于字符串的字面值,减少了硬编码
- 定义与SQL映射文件同名的mapper接口;
- 设置SQL映射文件的namespace属性为mapper接口全限定名;
- mapper接口中的方法需要与SQL映射文件中的SQL语句的ID保持一致;
原生方式开发:
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
<?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.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<UserEntity>
*/
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未设置为接口全限定名产生的问题
SQL映射文件中namespace未设置为接口全限定名会导致程序在执行的时候找不到namespace=接口全限定名所对应的SQL映射文件。
解决方法:
基于注解方式
优点:去除XML配置,提高了开发效率;
缺点:SQL语句植入Java代码,如果需要修改SQL语句必须修改源码,会导致维护成本增加,基于XML方式维护性更强;
项目准备
项目结构
项目代码
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</groupId>
<artifactId>mybatis-annotation</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</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<UserEntity>
*/
@Select("select * from tb_user")
List<UserEntity> listUserByAnnotation();
}
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="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代理开发(优化版)
在基于XML方式-mapper代理开发的基础上进行优化:
- SQL映射文件需要与mapper接口的包名结构和文件名称保持一致
注意:虽然文件名称需要保持一致,但是文件名称的大小写不敏感,也就是说命名为userMapper.xml或者usermapper.xml都是可行的。
- 修改mybatis-config.xml,使用扫包方式注册mapper
基于注解方式(优化版)
在基于注解方式的基础上进行优化:只需要修改mybatis-config.xml,使用扫包方式注册mapper即可。(请参考上述第二个步骤)
注册映射文件(resource、class、package三者的区别)
注册方式 | 注册对象 | 限制条件 |
---|---|---|
resource | 注册单个映射文件 | 直接加载映射文件,没有限制映射文件的包名结构和文件名称,非常灵活,不易出错 |
class | 注册单个mapper接口 | SQL映射文件需要与mapper接口的包名结构和文件名称保持一致 |
package | 注册包名下所有的mapper接口 | SQL映射文件需要与mapper接口的包名结构和文件名称保持一致 |