创建一个简单的Mybatis项目
一、创建一个简单的Mybatis项目
浅说一下mybatis的原理(目前理解):代替了原来Dao层(数据持久层)每次使用都需要connection连接数据库的操作,使用xml文件的方式,配置一次数据库的连接,之后使用Dao层的方法不再需要专门连接;同时将Dao层中实现接口的方法(sql语句)改用为xml文件实现
1.mybatis在线文档
https://mybatis.net.cn/getting-started.html
2.创建一个Maven项目
3.在pom.xml加入Maven依赖
<!--mybatis依赖-->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<!--mysql-connector依赖-->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!--单元测试的依赖,方便调试-->
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
4.在resource中创建mybatis配置文件
<!--
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"/>
<!--url在idea连接数据库时查看-->
<property name="url" value="jdbc:mysql://localhost:3306"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!--每个Mapper.xml(之后会创建)都需要在此处注册-->
<!--
<mappers>
<mapper resource=""/>
</mappers>
-->
</configuration>
5.整体包的结构如下
6.接下来创建utils包和MybatisUtils类
MybatisUtils类的作用是利用SqlSessionFactory创建一个SqlSession类,用于操作之后接口中的方法
package com.Gw.utils;
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;
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
/*
简单来说只用三句话,意思是从resource资源文件中以流形式得到xml配置文件,创建SqlSessionFactory,并创建SqlSession
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
*/
static {
//此处填写刚才的配置文件
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
7.编写Dao层
先说明一下实体类包pojo中的User类,实际由id、name、pwd组成,有对应的set、get方法和构造函数
本文省略了与数据库连接的部分,与数据库中数据的创建,给实例图读者自行创建、连接
在UserMapper中创建sql语句的接口
package com.Gw.dao;
import com.Gw.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> getUserList();
//根据id查询用户
User getUserById(int id);
//插入用户
void addUser(User user);
//修改用户
int updateUser(User user);
//删除一个用户
int deleteUser(int id);
}
在UserMapper.xml中实现对应的sql查询
<?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">
<!--namespace为名空间,对应着接口的位置-->
<mapper namespace="com.Gw.dao.UserMapper">
<!--select查询语句,id对应着接口中的方法名,在select中对应sql语句 -->
<select id="getUserList" resultType="com.Gw.pojo.User">
select * from mybatis.user
</select>
<select id="getUserById" parameterType="int" resultType="com.Gw.pojo.User">
select * from mybatis.user where id=#{id}
</select>
<insert id="addUser" parameterType="com.Gw.pojo.User">
insert into mybatis.user(id, name, pwd) values (#{id}, #{name}, #{pwd});
</insert>
<update id="updateUser" parameterType="com.Gw.pojo.User">
update mybatis.user set name =#{name},pwd=#{pwd} where id = #{id};
</update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id}
</delete>
</mapper>
<!--标签中有select、insert、update、delete语句,与sql中的对应-->
<!--说明一下标签中关键字的含义(与原Dao层的实现方法对应更好理解),id为接口中的方法名,parameterType传入方法的参数类型,resultType表示返回值类型,#{}表示从程序中(方法参数中)获取变量-->
<!--此例中当传进来对象为User时,在获取变量时只可以用#{id},#{name},#{pwd},如果想更改参数的名字,可以传进一个map对象,将原对象的变量名改为map中的key即可-->
8.测试执行
在test包中创建与main包中的相同结构,创建UserMapperTest类,具体参考5
使用junit进行测试
说明:在使用UserMapper中的方法时,需要先通过MybatisUtils创建SqlSession,再利用SqlSession通过UserMapper的接口获得mapper映射,之后就可以通过mapper对象调用UserMapper中的方法
package com.Gw.Dao;
import com.Gw.dao.UserMapper;
import com.Gw.pojo.User;
import com.Gw.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.jupiter.api.Test;
import java.util.List;
public class UserMapperTest {
@Test
public void test(){
//第一步:获取SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//第二步:执行sql语句
//方法一:getMapper
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
//方法二:不推荐
List<User> list = sqlSession.selectList("com.Gw.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user.getId() + " " + user.getName() + " " + user.getPwd());
}
sqlSession.close();
}
@Test
public void getUserById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.getUserById(1).getName());
}
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(4);
user.setName("小芳");
user.setPwd("123456");
mapper.addUser(user);
//提交事务,修改完一定要提交事务
sqlSession.commit();
sqlSession.close();
}
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.updateUser(new User(1,"李华","456789"));
sqlSession.commit();
sqlSession.close();
}
@Test
public void deleteUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser(2);
sqlSession.commit();
sqlSession.close();
}
@Test
public void getUserLike(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userLike = mapper.getUserLike("%李%");
for (User user : userLike) {
System.out.println(user.getName() + " " + user.getPwd());
}
sqlSession.close();
}
}
二、配置解析
在config-mybatis.xml中必须按照此顺序设置
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
1.environment
1.事务管理器(transactionManager)
在Mybatis中有两种类型的事务管理器,JDBC和MANAGED
- JDBC – 这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED – 这个配置几乎没做什么。
如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器,因为 Spring 模块会使用自带的管理器来覆盖前面的配置。
2.数据源(dataSource)
- POOLED– 这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
- UNPOOLED– 这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形。
- JNDI – 这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。
2.属性(properties)
- 可以引入外部文件db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&characterEncoding=UTF-8
username=root
password=123456
使用时需在mybatis-config.xml加入properties标签
<properties resource="db.resource"/>
<!--然后可直接调用-->
<property name="username" value="${username}"></property>
- 可以在xml中插入properties标签
<properties>
<property name="username" value="root"/>
</properties>
- 当二者都存在时,先使用外部配置文件
3.类型别名(typeAliases)
简化使用实体类中的类名
<!--为java类起别名-->
<typeAliases>
<typeAlias alias="User" type="com.Gw.pojo.User"/>
</typeAliases>
<!--为包起别名,包内的类可以小写直接用,不用再写一长串-->
<typeAliases>
<package name="com.Gw.pojo"/>
</typeAliases>
在实体类比较少的时候使用第一种,多的时候使用第二种;
第一种可以自定义别名,第二种自定义别名则需要在实体上加注解
@Alias("user")
public class user{}
4.设置(settings)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
重点掌握
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 |
true | false | false |
useGeneratedKeys | 允许 JDBC 支持自动生成主键,需要数据库驱动支持。如果设置为 true,将强制使用自动生成主键。尽管一些数据库驱动不支持此特性,但仍可正常工作(如 Derby)。 | true | false | False |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未设置 |
5.其他配置
typeHandlers(类型处理器)
objectFactory(对象工厂)
插件(plugin)
- mybatis-generator-core
- mybatis-plus-boot-starter
- 通用mapper
6.映射器(mappers)
1.原始方式
<mappers>
<mapper resource="com/Gw/dao/UserMapper.xml"/>
</mappers>
2.使用class的文件绑定注册
<mappers>
<mapper class="com.Gw.dao.UserMapper"/>
</mappers>
3.通过package
<mappers>
<package name="com.Gw.dao"/>
</mappers>
注意:2、3的接口和它的Mapper配置文件必须同名并且接口和它的配置文件必须在一个包下
7.作用域和生命周期
不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder
- 一旦创建了 SqlSessionFactory,就不再需要它了
- 局部变量
SqlSessionFactory
-
可以想象成数据库连接池
-
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。
-
SqlSessionFactory 的最佳作用域是应用作用域。
-
在应用运行期间不要重复创建多次有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession
-
每一个独享一个线程,与连接池连接
-
每个线程都应该有它自己的 SqlSession 实例。
-
它的最佳的作用域是请求或方法作用域。
-
考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。
总结:
mapper就相当于一个业务
三、解决实体类和数据库名字不一致的问题
pojo中为password
数据库中为pwd
解决方法:
- 起别名
<select id="getUserById" resultType="com.Gw.pojo.User">
select id, name, pwd as password from mybatis.user where id = #{id}
</select>
结果集映射(resultMap)简介
resultMap
元素是 MyBatis 中最重要最强大的元素。- ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
<!--使用举例-->
<!--建立名为UserMap的结果映射,其中column表示数据库中的字段,property表示实体类中的属性-->
<resultMap id="UserMap" type="User">
<result column="pwd" property="password"></result>
</resultMap>
<!--resultMap指定结果映射为UserMap-->
<select id="getUserById" parameterType="int" resultMap="UserMap">
select * from mybatis.user where id=#{id}
</select>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术