MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录
MyBatis官网:mybatis – MyBatis 3 | 简介
一、引入 mybatis 依赖
<!-- mybatis依赖 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>
<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<!-- lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>compile</scope>
</dependency>
二、入门案例 ( mapper代理方式 )
案例项目结构如下
第一步. 配置 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">
<!-- mybatis主配置文件 -->
<configuration>
<!-- 配置环境 -->
<environments default="dev">
<!-- 数据源 -->
<environment id="dev">
<!-- 配置事务的类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(链接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的基本信息 -->
<property name="driver" value="{{ 数据库驱动 }}"/>
<property name="url" value="{{ 数据库连接url }}"/>
<property name="username" value="{{ 用户名 }}"/>
<property name="password" value="{{ 密码 }}"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件 -->
<mappers>
<!-- 使用注解则使用 class 指定dao的全类名 -->
<mapper class="dao.UserDao"/>
</mappers>
</configuration>
第二步. 配置 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="dao.UserDao">
<!-- 查找所有 -->
<select id="findAll" resultType="pojo.User">
select * from testMybatis.user
</select>
</mapper>
第三步. 编写 实体类 和 mapper 接口
实体类
@Data ( 提供类的get、set、equals、hashCode、toString等方法 )
@NoArgsConstructor ( 提供类的无参构造方法 )
@AllArgsConstructor ( 提供类的全部参数构造方法 )
学习 lombok 插件及注解:稍后更新
// domain.User
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
接口类
// dao.UserDao
public interface UserDao {
/**
* 使用配置文件 查询所有
* @return
*/
List<User> findAll();
}
第四步. 编写测试类
public class Test {
private InputStream inputStream;
private SqlSession sqlSession;
private static UserDao userDao;
@Before //用于在测试方法之前执行
public void init()throws Exception{
//1.读取配置文件
inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//2.创建sqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(inputStream);
//3.使用工厂生产SqlSession对象
sqlSession = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao = sqlSession.getMapper(UserDao.class);
}
@After //用于在测试方法之后执行
public void destroy()throws Exception{
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
inputStream.close();
}
@Test
public void findAllTest(){
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
// java8 方法引用
users.forEach(System.out::println);
}
}
注意:
MyBatis进行 增删改 操作时需要进行事务控制
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
三、MyBatis 主配置文件 ( 核心配置文件 )
resource/mybatis-config.xml
具体配置内容请移步:MyBatis主配置文件_YaoQi·的博客-CSDN博客
四、MyBatis 映射配置文件 ( 接口配置文件 )
resource/dao/xxxMapper.xml
具体配置内容请移步:MyBatis接口配置文件_YaoQi·的博客-CSDN博客_接口配置文件
官网:mybatis – MyBatis 3 | XML 映射器
五、MyBatis 动态sql
具体配置内容请移步:MyBatis动态sql_YaoQi·的博客-CSDN博客
官网:mybatis – MyBatis 3 | 动态 SQL
六、 MyBatis-Generator 代码生成器
官网:MyBatis Generator Core – Introduction to MyBatis Generator
中文文档:MyBatis Generator介绍 · Java 开源项目中文文档 · 看云
1. pom.xml
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<configurationFile>src/main/resources/generator/generator-config.xml</configurationFile>
<!-- 是否覆盖 -->
<overwrite>true</overwrite>
<!-- 是否输出详细信息 -->
<verbose>true</verbose>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
2. generator-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="Mysql" targetRuntime="MyBatis3" defaultModelType="flat">
<!-- 自动检查关键字,为关键字增加反引号 -->
<property name="autoDelimitKeywords" value="true"/>
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!--覆盖生成XML文件-->
<plugin type="org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin" />
<!-- 生成的实体类添加toString()方法 -->
<plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
<!-- 不生成注释 -->
<!-- <commentGenerator>-->
<!-- <property name="suppressAllComments" value="true"/>-->
<!-- </commentGenerator>-->
<!---数据库连接信息-->
<jdbcConnection driverClass="{driver}"
connectionURL="{url}"
userId="{username}"
password="{password}">
</jdbcConnection>
<!--自动 domain[Bean]类的位置 -->
<javaModelGenerator targetProject="src\main\java"
targetPackage="{xxx.pojo}"/>
<!--自动 mapper xml的位置 -->
<sqlMapGenerator targetProject="src\main\resources"
targetPackage="mapper"/>
<!--自动 mapper类[接口]的位置 -->
<javaClientGenerator targetProject="src\main\java"
targetPackage="{xxx.mapper}"
type="XMLMAPPER"/>
<table tableName="{tableName}"></table>
</context>
</generatorConfiguration>
3. 使用 IDEA 生成
七、 注解开发
将mapper修改为包扫描
<mappers>
<package name="dao"/>
</mappers>
crud (注解在dao接口的方法上)
@select("{sql语句}")
@instert("{sql语句}")
@update("{sql语句}")
@delete("{sql语句}")
复杂映射
一对一
方式一
@select("sql")
@Results({
@Result(property = "xxx", column = "xxx"),
@Result(property = "xxx.xxx", column = "xxx"),
...
})
方式二
@select("sql")
@Results({
@Result(property = "xxx", column = "xxx"),
@Result(
property = "xxx", // 要封装的属性名称
javatype = Xxxx.class, // 要封装的实体类型
column = "xxx", // 需要根据哪个字段去查询数据
// select 代表查询哪个接口的方法获得数据
one = @One(select = "方法的全类名.方法名")
),
...
})
一对多
@select("sql")
@Results({
@Result(property = "xxx", column = "xxx"),
@Result(
property = "xxx", // 要封装的属性名称
javatype = Xxx.class, // 要封装的实体类型
column = "xxx", // 需要根据哪个字段去查询数据
// select 代表查询哪个接口的方法获得数据
many = @Many(select = "方法的全类名.方法名")
),
...
})
多对多
@select("sql")
@Results({
@Result(id= true, property = "xxx", column = "xxx"),
@Result(
property = "xxx", // 要封装的属性名称
javatype = Xxx.class, // 要封装的实体类型
column = "xxx", // 需要根据哪个字段去查询数据
// select 代表查询哪个接口的方法获得数据
many = @Many(select = "方法的全类名.方法名")
),
...
})
八、MyBatis 缓存 ( 稍后更新 )
适用于 :经常查询且不经常查询的数据,数据的正确与否对最终结果影响不大的
不适用 :经常改变的数据,数据的正确性要求高的(商品库存、银行汇率、股市牌价等)
一级缓存
指MyBatis中的 SqlSession 对象的缓存
当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供的一块区域中。该区域的结构是一个Map,当我们再次查询同样的数据,MyBatis会先去SqlSession中查询是否有,有的话直接拿出来用,当SqlSession对象消失时,MyBatis的一级缓存也就消失了。
mybatis和spring整合后进行mapper代理开发,不支持一级缓存。
当调用了SqlSession中的 增、删、改、commit()、close() 方法,会自动清空缓存
二级缓存
指MyBatis中的 SqlSessionFactory 对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
使用步骤:
一、让MyBatis框架支持二级缓存(在 mybatis-config.xml 中配置)
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
二、让当前的映射配置文件支持二级缓存(在 XxxDao.xml 中配置)
<cache/>
三、让当前操作支持二级缓存(在select标签中配置)
<select ... useCache="true">
...
</select>
-
二级缓存中存储的是数据,不是对象,比对为 false
九、整合 SSM
1. 修改mybatis核心配置文件:mybatis-config.xml
将以下三个配置转移到 applicationContext.xml
<!-- 配置jdbc properties -->
<properties resource="jdbcConfig.properties"/>
<!-- 配置数据源 -->
<environments default="mysql">
...
</environments>
<!-- 指定映射配置文件 -->
<mappers>
<package name="dao"/>
</mappers>
2. 添加依赖:pom.xml
<!-- C3P0连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
3. 修改spring核心配置文件:applicationContext.xml
<!-- 加载properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 加载数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置sessionFactory -->
<bean id="sqlSessionFactory", class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 加载mybatis配置文件 -->
<property name="configLocation" value="mybatis-config.xml"/>
</bean>
<!-- 扫描Mapper所在的包 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackge" value="dao"/>
</bean>
4. 修改:ServiceImpl
@Autowired
private XxxxDao xxxDao;
5. 声明式事务控制
修改spring核心配置文件:applicationContext.xml
<!-- 声明式事务控制 -->
<!-- 平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务增强 -->
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- 事务的aop织入 -->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* service.impl.*.*(..))" />
</aop:config>
十、整合 Springboot
1. pom.xml
<dependency>
<groundId>org.springframework.boot</groundId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groundId>org.springframework.boot</groundId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groundId>org.springframework.boot</groundId>
<artifactId>spring-boot-starter-stater</artifactId>
</dependency>
<dependency>
<groundId>org.springframework.boot</groundId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groundId>mysql</groundId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groundId>com.alibaba</groundId>
<artifactId>druid-spring-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groundId>org.mybatis.spring.boot</groundId>
<artifactId>mybatis-spring-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
2. application.yml
spring:
datasource:
druid:
driver-class-name: xxx
url: xxx
username: xxx
password: xxx
# mybatis
mybatis:
# mapper 存放位置
mapper-location: classpath: /xxx
# 是否开启驼峰命名
map-underscore-to-camel-case: true
# 包别名,实体类
type-aliases-package: xxx