Mybaits3
写在文章前面
根据B站大佬狂神说的视频学习的Mybatis,然后整理的笔记。
- 视频合集地址:狂神说Java-Mybatis教程
- jdk:1.8
- Maven:3.6.1
- mysql:5.7.36
- 开发工具:IDEA 2022
- mybaits3中文官网:https://mybatis.org/mybatis-3/zh/index.html
- github地址:https://github.com/mybatis/mybatis-3
- 本笔记中源代码下载:https://download.csdn.net/download/u011301348/87774404
1、简介
1、1 什么是Mybatis
- 是一款优秀的持久层框架。
- 是一个开源、轻量级的,JDBC的替代方案。
- 支持自定义 SQL、存储过程以及高级映射。
- 免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
- 可以通过简单的XML或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
- 内部封装了JDBC,简化了加载驱动、创建连接、创建 statement 等繁杂的过程,开发者只需要关注 SQL 语句本身。
- 是一个半自动化的ORM框架 (Object Relationship Mapping) —>对象关系映射
1、2 MyBatis历史
- MyBatis本是apache的一个开源项目iBatis,2002 年由 Clinton Begin 发布。
- 2010 年从 Apache 迁移到 Google,并改名为 MyBatis。
- 2013 年又迁移到了 Github。
1、3 MyBatis优点
- 是免费且开源的。
- 与 JDBC 相比,减少了 50% 以上的代码量。
- 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件。
- 灵活:不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
- 提供 XML 标签,支持编写动态 SQL 语句。
- 提供映射标签,支持对象与数据库的 ORM 字段关系映射。
- 使用的人多!公司需要!随大流!
1、4 MyBatis缺点
- 编写 SQL 语句工作量较大,对开发人员编写 SQL 语句的功底有一定要求。
- SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
2、Mybatis第一个程序
2、1 创建数据库、表
CREATE DATABASE `mybatis`;
USE `mybatis`;
CREATE TABLE `user`(
`id` INT NOT NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO `user`(`id`,`name`,`pwd`) VALUES (1,'狂神','123456'),(2,'张三','123456'),(3,'李四','123890')
2、2 导入mybatis、mysql、junit依赖
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<!--mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2、3 编写配置文件,文件位置一般放在resources目录中
- 数据库配置文件,db.properties
Driver=com.mysql.jdbc.Driver
Url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&characterEncoding=utf-8
UserName=root
PassWord=123456
- Mybatis核心配置文件,mybaits-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文件 -->
<properties resource="db.properties"></properties>
<!-- 设置别名,使用的时候直接用别名就行 -->
<typeAliases>
<!-- 方式一 -->
<typeAlias type="com.liushq.pojo.User" alias="user" />
<!-- 方式二 给指定包下所有实体设置别名,默认别名为类名的首字目小写形式,例如:User类的别名为user-->
<package name="com.liushq.pojo" />
</typeAliases>
<!-- 配置mybatis运行环境 -->
<environments default="development">
<environment id="development">
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<!-- MySQL数据库驱动 -->
<property name="driver" value="${Driver}"/>
<!-- 连接数据库的URL -->
<property name="url" value="${Url}" />
<property name="username" value="${UserName}" />
<property name="password" value="${PassWord}" />
</dataSource>
</environment>
</environments>
<!-- 将mapper文件加入到配置文件中 -->
<mappers>
<mapper resource="com/liushq/mapper/UserMapper.xml" />
</mappers>
</configuration>
2、4 创建项目
- 创建一个普通maven项目mybatis-study,并删除src文件夹。
完整的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.liushq</groupId>
<artifactId>mybatis-study</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
<build>
<!--为防止mapper.xml文件无法输出,需进行如下配置-->
<resources>
<!-- src/main/java文件夹下,可以存放 *.properties、*.xml 文件,不用过滤 -->
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
- 在项目下新建模块mybatis-01,并完善项目结构及配置。
- 在utils包下,编写MyBatis工具类,MyBaitsUtils
package com.liushq.utils;
public class MyBaitsUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
- 在pojo包下,编写User实体类
package com.liushq.pojo;
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
- 在mapper包下,编写UserMapper接口
package com.liushq.mapper;
public interface UserMapper {
List<User> getUserList();
List<User> getUserListByMap(Map<String,Object> map);
User getUserInfo(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
- 在resourses下,新建mapper文件夹,并在该文件夹下编写UserMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liushq.mapper.UserMapper">
<select id="getUserList" resultType="com.liushq.pojo.User">
select * from user;
</select>
<select id="getUserListByMap" parameterType="map" resultType="com.liushq.pojo.User">
select * from mybatis.user where name like '%${name}%';
</select>
<select id="getUserInfo" parameterType="int" resultType="com.liushq.pojo.User">
select * from mybatis.user where id=#{id};
</select>
<insert id="addUser" parameterType="com.liushq.pojo.User">
insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd})
</insert>
<update id="updateUser" parameterType="com.liushq.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>
- 在service包下,编写UserService接口及实现类
package com.liushq.service;
public interface UserService {
List<User> getUserList();
List<User> getUserListByMap(String name);
User getUserInfo(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
package com.liushq.service.Impl;
public class UserServiceImpl implements UserService {
private SqlSession sqlSession = MyBaitsUtils.getSqlSession();
private UserMapper mapper = sqlSession.getMapper(UserMapper.class);
@Override
public List<User> getUserList() {
List<User> list=mapper.getUserList();
sqlSession.close();
return list;
}
@Override
public List<User> getUserListByMap(String name) {
Map<String,Object> map=new HashMap<>();
map.put("name",name);
List<User> list=mapper.getUserListByMap(map);
sqlSession.close();
return list;
}
@Override
public User getUserInfo(int id) {
User user=mapper.getUserInfo(id);
sqlSession.close();
return user;
}
@Override
public int addUser(User user) {
int res=mapper.addUser(user);
sqlSession.commit();
sqlSession.close();
return res;
}
@Override
public int updateUser(User user) {
int res=mapper.updateUser(user);
sqlSession.commit();
sqlSession.close();
return res;
}
@Override
public int deleteUser(int id) {
int res=mapper.deleteUser(id);
sqlSession.commit();
sqlSession.close();
return res;
}
}
- 编写测试类
package com.liushq.service;
import com.alibaba.fastjson.JSONObject;
public class UserServiceTest {
private UserService service=new UserServiceImpl();
@Test
public void getUserList(){
List<User> userList = service.getUserList();
for (User user : userList) {
System.out.println(JSONObject.toJSONString(user));
}
}
@Test
public void getUserListByMap(){
List<User> userList = service.getUserListByMap("i");
for (User user : userList) {
System.out.println(user);
}
}
@Test
public void getUserInfo(){
User user = service.getUserInfo(1);
System.out.println(user);
}
@Test
public void addUser(){
User user=new User(5,"xiaoma1","123123");
int res= service.addUser(user);
System.out.println(res>0?"添加成功":"添加失败");
}
@Test
public void updateUser(){
User user=new User(5,"xiaoma1111","123123111");
int res= service.updateUser(user);
System.out.println(res>0?"修改成功":"修改失败");
}
@Test
public void deleteUser(){
int res= service.deleteUser(4);
System.out.println(res>0?"删除成功":"删除失败");
}
}
- json处理,需要在mybatis-01的pom.xml中添加json依赖,这里用的是com.alibaba.fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
<scope>test</scope>
</dependency>
- 测试结果,getUserList方法
- 完整项目结构图
3、XML映射器(Mapper.xml)及CRUD操作
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.liushq.mapper.UserMapper">
</mapper>
- namespace:命名空间
- 绑定DAO接口,必须跟某个接口同名。
- 相当于通过xml配置文件,实现了mapper接口。
- select:查询标签,对应sql中的select查询语句。
- id:对应mapp接口中的接口名称。
- parameterType:接口的参数类型。
- resultType:接口的返回结果类型。
- resultMap:返回外部 resultMap 的命名引用。
<select id="getUserInfo" parameterType="int" resultType="com.liushq.pojo.User">
select * from mybatis.user where id=#{id};
</select>
- insert:插入数据标签,对应sql中的insert语句。
<insert id="addUser" parameterType="com.liushq.pojo.User">
insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd})
</insert>
- update:更新数据标签,对应sql中的update语句。
<update id="updateUser" parameterType="com.liushq.pojo.User">
update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
</update>
- delete:删除标签,对应sql中的delete语句。
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id}
</delete>
注意点:增、删、改操作需要提交事务!
4、Mybatis-config.xml配置解析
mybatis中可以配置的内容如下:
<!-- 需要严格注意元素节点的顺序!顺序不对会报错 -->
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器) <!--用的少,自行看官网说明-->
objectFactory(对象工厂) <!--用的少,自行看官网说明-->
plugins(插件) <!--用的少,自行看官网说明-->
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
4、1 properties(属性)
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。例如:
<!-- 这是一种写法 -->
<properties resource="db.properties"></properties>
<!-- 还可以在标签引用内,再添加属性 -->
<properties resource="db.properties">
<property name="UserName" value="root"/>
<property name="PassWord" value="123456"/>
</properties>
如果一个属性在不只一个地方进行了配置,比如:UserName跟PassWord,在db.properties配置文件里有,在properties标签中也有,那么,MyBatis 将按照下面的顺序来加载:
- 首先读取在 properties 标签元素体内指定的属性。
- 然后根据 properties 元素中的 resource 属性读取引用的配置文件,并覆盖之前读取过的同名属性。
- 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。
- 意思就是在properties标签中设置的属性,会被在db.properties配置文件中的同名属性所覆盖。
设置好的属性后,就可以在整个配置文件中用来替换需要动态配置的属性值。例如:
<dataSource type="POOLED">
<!-- MySQL数据库驱动 -->
<property name="driver" value="${Driver}"/>
<!-- 连接数据库的URL -->
<property name="url" value="${Url}" />
<property name="username" value="${UserName}" />
<property name="password" value="${PassWord}" />
</dataSource>
4、2 settings(设置)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。这里只罗列一些常用的、比较重要的,其他的可以自行看官网文档。
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true或false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 | true或false | false |
mapUnderscoreToCamelCase | 是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。 | true或false | false |
logImpl | 指定 MyBatis 所用日志的具体实现,未指定时将自动查找。 | SLF4J、LOG4J(3.5.9 起废弃)、LOG4J2、 JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING | 未设置 |
一个配置完整的 settings 元素的示例如下:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="safeResultHandlerEnabled" value="true"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
<setting name="defaultScriptingLanguage" value="org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"/>
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumTypeHandler"/>
<setting name="callSettersOnNulls" value="false"/>
<setting name="returnInstanceForEmptyRow" value="false"/>
<setting name="logPrefix" value="exampleLogPreFix_"/>
<setting name="logImpl" value="SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING"/>
<setting name="proxyFactory" value="CGLIB | JAVASSIST"/>
<setting name="vfsImpl" value="org.mybatis.example.YourselfVfsImpl"/>
<setting name="useActualParamName" value="true"/>
<setting name="configurationFactory" value="org.mybatis.example.ConfigurationFactory"/>
</settings>
4、3 类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<!-- 方式一:直接配置类名的别名 -->
<typeAliases>
<typeAlias type="com.liushq.pojo.User" alias="User" />
</typeAliases>
<!-- 方式二:指定一个包名,MyBatis会在包名下搜索需要的实体,别名默认为类名的首字母小写形式 -->
<typeAliases>
<package name=""com.liushq.pojo"/>
</typeAliases>
在UserMapper.xml中,没设置别名前
<select id="getUserList" resultType="com.liushq.pojo.User">
select * from user;
</select>
设置别名后,resultType中的类名可以直接使用别名
<select id="getUserList" resultType="User">
select * from user;
</select>
官网中有详细的别名介绍,可以自行查看。
4、4 环境配置(environments)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
<!-- 配置mybatis运行环境 在default中指定使用哪个环境,environment 可以有多个-->
<environments default="development">
<!-- development开发环境-->
<environment id="development">
<!-- 使用JDBC的事务管理 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 POOLED 利用“池”的概念将 JDBC 连接对象组织起来 -->
<dataSource type="POOLED">
<!-- MySQL数据库驱动 -->
<property name="driver" value="${Driver}"/>
<!-- 连接数据库的URL -->
<property name="url" value="${Url}" />
<property name="username" value="${UserName}" />
<property name="password" value="${PassWord}" />
</dataSource>
</environment>
<!-- test测试环境-->
<environment id="test">
...
</environment>
</environments>
- environment:配置具体环境,可以有多个,id必须唯一。
- transactionManager:事务管理器,有JDBC、MANAGED 2种可选。
- JDBC:这个配置直接使用了 JDBC 的提交和回滚功能,它依赖从数据源获得的连接来管理事务作用域。
- MANAGED:这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文)。 默认情况下它会关闭连接。
- dataSource:数据源,有UNPOOLED、POOLED、JNDI 3种可选。
- UNPOOLED:这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。
- POOLED:这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间。 这种处理方式很流行,能使并发 Web 应用快速响应请求。
- JNDI:这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用。
4、5 映射器(mappers)
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。
<mappers>
<!-- 方式一:使用相对于类路径的资源引用 -->
<mapper resource="mapper/UserMapper.xml"/>
<!-- 方式二:使用相对于类路径的资源引用 -->
<mapper class="com.liushq.mapper.UserMapper"/>
<!-- 将包内的映射器接口全部注册为映射器,接口和它的Mapper配置文件必须同名,且位于同一目录下 -->
<package name="com.liushq.mapper"/>
</mappers>
5、ResultMap用法
更新中。。。