Mybatis
持久层框架
内存:断电即失
数据持久化:数据库(JDBC)、IO文件持久化
第一个Mybatis程序
Mybatis中文文档https://mybatis.org/mybatis-3/zh/index.html
使用 Maven 来构建项目,将下面的依赖代码置于 pom.xml 文件中:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
配置mybatis-config.xml;XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)
<?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://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<!--对应的mapperXML文件位置-->
<mapper resource="com/flyfly/mapper/UserMapper.xml"/>
</mappers>
</configuration>
编写Mybatis工具类
//构建 SqlSessionFactory -->SqlSession
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
// 获取SqlSessionFactory对象
try {
String resource = "mybatis-config.xml";
InputStream inputStream = null;
inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//获取SqlSession实例
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
编写实体类User
public class User {
private String id;
private String username;
private String sex;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
编写对应的UserMapper接口
import java.util.List;
public interface UserMapper {
List<User> findAllUser();
}
编写对应的xml;
<!--namespace:命名空间;指对应的mapper类的位置
select后面的id指的是UserMapper接口中的方法名;resultType指返回的类型
-->
<?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.flyfly.mapper.UserMapper">
<select id="findAllUser" resultType="com.flyfly.pojo.User">
select * from user
</select>
</mapper>
编写方法进行测试
public class MybatisTest {
public static void main(String[] args) {
//获得SqlSession
SqlSession sqlSession= MybatisUtils.getSqlSession();
//获得mapper
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
List<User> userList=userMapper.findAllUser();
for (User user:userList) {
System.out.println(user);
}
sqlSession.close();
}
}
这里会报一个错误:找不到UserMapper.xml文件,问题原因Maven项目的过滤导致
解决方法:在pom.xml文件中进行资源配置
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*Mapper.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*Mapper.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
注意:
- 需要配置和数据库版本一致的数据库驱动jar
- 增删改需要提交事务
//增删改需要提交事务 int num= userMapper.AddUser(new User("3","three","男")); if (num>0){ System.out.println("插入成功"); //提交事务 sqlSession.commit(); }
配置解析MybatisConfig.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:引入类路径下的资源
url:引入网络路径或者磁盘路径下的资源
-->
<properties resource="dbconfig.properties"></properties>
<!-- 设置:定义mybatis的一些全局性设置 -->
<!-- <settings>
具体的参数名和参数值
<setting name="logImpl" value="LOG4J"/>
</settings> -->
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
<!-- 1、typeAliases别名处理器——类型名称:为一些类定义别名 (不区分大小写)
type:指定要起别名的类型全类名
alias:指定新别名
2、package:为某个包下的所有类批量取别名
name:指定包名(为当前包以及下面所有后代包的每一个类都起一个默认别名(类名小写)
3、批量取别名的情况下,在类中使用@Alias注解为某个类型指定新的别名
4、typeAlias为单个类取别名
-->
<typeAliases>
<package name="com.jxau.ssm.bean" />
<typeAlias type="com.jxau.ssm.bean.User" alias="User">
</typeAliases>
<!-- 类型处理器:定义Java类型与数据库中的数据类型之间的转换关系 -->
<!-- <typeHandlers></typeHandlers> -->
<!-- 对象工厂 -->
<!-- <objectFactory type=""></objectFactory> -->
<!-- plugins插件:mybatis的插件,插件可以修改mybatis的内部运行规则 -->
<!-- <plugins>
<plugin interceptor=""></plugin>
</plugins> -->
<!-- 环境:配置mybatis的环境 可以配置多个环境-->
<environments default="development">
<!-- 环境变量:可以配置多个环境变量,比如使用多数据源时,就需要配置多个环境变量 -->
<environment id="development">
<!-- 事务管理器 transactionManager-->
<transactionManager type="JDBC"/>
<!-- 数据源 使用连接池连接数据库-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 数据库厂商标识
支持多数据库厂商
type="DB_VENDOR",VendorDatabaseIdProvide
作用就是得到数据库厂商标识
-->
<!-- <databaseIdProvider type=""></databaseIdProvider> -->
<!-- 映射器:指定映射文件或者映射类 将sql映射注册到全局配置-->
<mappers>
<mapper resource="com/jxau/ssm/dao/UserMapper.xml"/>
<mapper resource="com/jxau/ssm/dao/UserMapperPlus.xml"/>
<mapper resource="com/jxau/ssm/dao/DepartmentMapper.xml"/>
<!-- <mapper class="com.jxau.ssm.dao.UserMapper.xml"/> -->
</mappers>
</configuration>
resultMap结果集映射
实体类的变量名和数据库列名不一致
//实体类变量
public class User {
private String id;
private String name;
private String sex;
}
//数据库列名
//id,username,sex
修改UserMapper.xml配置
<mapper namespace="com.flyfly.mapper.UserMapper">
<resultMap id="userMap" type="user">
<!--column:数据库表中的列名,property:实体类的变量名
可以对不同的进行修改(id和sex可以省略)
-->
<result column="id" property="id"/>
<result column="username" property="name"/>
<result column="sex" property="sex"/>
</resultMap>
<select id="findAllUser" resultMap="userMap">
select * from user
</select>
Mybatis执行流程
动态SQL
- if
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
- choose (when, otherwise)
当想 从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
- trim (where, set)
如果没有加 当第一个if没有时,会拼接后面的会带上AND导致SQL语句报错
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
- foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
动态SQL就是拼接sql语句
Mybatis缓存
**缓存:**存在内存中的临时数据
将用户常用的数据放置在缓存中,用户就不需要去磁盘中读取数据了,可以从缓存中进行读取数据,从而提高查询效率,解决了高并发系统的性能问题
**好处:**减少了和数据库的交互次数,减少了系统开销,提高系统效率
一级缓存(本地缓存:sqlSession)(默认开启)
与数据库同一次会话期间的数据会放到本地缓存中
以后查询同样的数据会直接从本地缓存中读取
如果之间进行了增删改会刷新缓存,或者缓存满了会清除一些数据,或者手动清除缓存
二级缓存(全局缓存)
基于namepace级别的二级缓存,一个名称空间对应一个二级缓存
机制
一个会话查询一条数据,这条数据就会保存到一级缓存中;当前会话关闭,则一级缓存就没有了;我们想要会话关闭了,可以将一级缓存中的数据保存到二级缓存中;新的会话,进行相同的查询时,就直接从二级缓存中进行读取;不同的mapper查询会存到不同的map中
开启需要在Mybatis_config.xml文件进行配置
在表签下配置
cacheEnabled 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 true | false true
<settings>
<setting name="cacheEnabled" value="true"></setting>
</settings>
在对应的mapper.xml进行缓存配置
<cache eviction="LRU" flushInterval="100000" readOnly="true" size="1024"/>
用户查询顺序:
用户----->二级缓存----->一级缓存------->数据库