目录
10.1.3 对一映射方式1:通过关联对象打点调用属性的方式
10.1.4 对一映射方式2:直接引用关联对象的Mapper映射
10.1.5 对一映射方式3:直接引用关联对象的单独查询的方法
13.2 一级缓存:自动开启,SqlSession级别的缓存
(1)添加一张新表
- CREATE TABLE `gamerecord` (
- `recordId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
- `homeTeamId` int DEFAULT NULL COMMENT '主队ID',
- `gameDate` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '比赛日期',
- `score` int DEFAULT NULL COMMENT '得分',
- `visitingTeamId` int DEFAULT NULL COMMENT '客队ID',
- PRIMARY KEY (`recordId`),
- KEY `homeTeamId` (`homeTeamId`),
- KEY `visitingTeamId` (`visitingTeamId`),
- CONSTRAINT `gamerecord_ibfk_1` FOREIGN KEY (`homeTeamId`) REFERENCES `team` (`teamId`),
- CONSTRAINT `gamerecord_ibfk_2` FOREIGN KEY (`visitingTeamId`) REFERENCES `team` (`teamId`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
(2)实体类
- package com.lxy.pojo;
-
- import java.util.Date;
-
- public class GameRecord {
- private String recordId;
- private Integer homeTeamId;
- private Date gameDate;
- private Integer score;
- private Integer visitingTeamId;
-
- public String getRecordId() {
- return recordId;
- }
-
- public void setRecordId(String recordId) {
- this.recordId = recordId;
- }
-
- public Integer getHomeTeamId() {
- return homeTeamId;
- }
-
- public void setHomeTeamId(Integer homeTeamId) {
- this.homeTeamId = homeTeamId;
- }
-
- public Date getGameDate() {
- return gameDate;
- }
-
- public void setGameDate(Date gameDate) {
- this.gameDate = gameDate;
- }
-
- public Integer getScore() {
- return score;
- }
-
- public void setScore(Integer score) {
- this.score = score;
- }
-
- public Integer getVisitingTeamId() {
- return visitingTeamId;
- }
-
- public void setVisitingTeamId(Integer visitingTeamId) {
- this.visitingTeamId = visitingTeamId;
- }
- }
(3)创建实体类的mapper接口
- package com.lxy.mapper;
-
- import com.lxy.pojo.GameRecord;
-
- public interface GameRecordMapper {
- int add(GameRecord record);
- }
(4)修改配置文件
添加GameRecordMapper.xml文件
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.GameRecordMapper">
-
- <insert id="add" parameterType="com.lxy.pojo.GameRecord">
- <selectKey keyProperty="recordId" order="BEFORE" resultType="java.lang.String">
- select uuid()
- selectKey>
- INSERT INTO `mybatis`.`gamerecord` (`recordId`, `homeTeamId`, `gameDate`, `score`, `visitingTeamId`)
- VALUES (#{recordId}, #{homeTeamId},default, #{score}, #{visitingTeamId})
- insert>
- mapper>
(5)测试类
- package com.lxy.test;
-
- import com.lxy.mapper.GameRecordMapper;
- import com.lxy.pojo.GameRecord;
- import com.lxy.util.MybatisUtil;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
-
- public class GameRecordMapperTest {
- private SqlSession sqlSession = MybatisUtil.getSqlSession();
-
- @Test
- public void testAdd(){
- GameRecordMapper mapper = sqlSession.getMapper(GameRecordMapper.class);
- GameRecord record = new GameRecord();
- record.setHomeTeamId(1014);
- record.setVisitingTeamId(1019);
- record.setScore(99);
- int add = mapper.add(record);
- sqlSession.commit();
- System.out.println("add结果"+add);
- System.out.println(record.getRecordId());
- }
- }

使用before方法能为insert方法添加一个recordId,可以在创建对象的时候不传参数
(1)在TeamMapper接口中添加addAfter方法
- package com.lxy.mapper;
-
-
- import com.lxy.pojo.Team;
-
- import java.util.List;
-
- public interface TeamMapper {
- List
queryAll(); - Team queryById(Integer teamId);
- int add(Team team);
- int update(Team team);
- int del(Integer teamId);
- int addAfter(Team team);
- }
-
(2)在TeamMapper.xml中添加addAfter方法
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.TeamMapper">
-
- <insert id="addAfter" parameterType="com.lxy.pojo.Team">
- <selectKey keyProperty="teamId" order="AFTER" resultType="java.lang.Integer">
- select LAST_INSERT_ID()
- selectKey>
- INSERT INTO `team` (`teamName`, `location`, `createTime`)
- VALUES (#{teamName}, #{location}, #{createTime})
- insert>
- mapper>
(3)编写测试类
- @Test
- public void testAddAfter(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- Team team = new Team();
- team.setTeamName("lxy");
- team.setLocation("shanghai");
- int i = mapper.addAfter(team);
- sqlSession.commit();
- System.out.println(i);
- System.out.println("新增id:"+team.getTeamId());
- }
虽然没添加id,但是使用after方法可以直接获取自动添加后的id
parameterType:接口中方法参数的类型,类型必须是完全限定名或别名(稍后讲别名)。该属性非必须,因为Mybatis框架能自行判断具体传入语句的参数,默认值为未设置(unset)。
当sql语句中需要多个参数时,就不能使用parameterType方法了。
(1)首先在TeamMapper接口中添加方法声明
List queryByRange(int min, int max);
(2)在TeamMapper.xml中添加节点
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.TeamMapper">
-
-
- <select id="queryByRange" resultType="com.lxy.pojo.Team">
- select * from team where teamId >=#{param1} and teamId <=#{param2};
- select>
- mapper>
(3)编写测试方法
- package com.lxy.test;
-
- import com.lxy.mapper.TeamMapper;
- import com.lxy.pojo.Team;
- import com.lxy.util.MybatisUtil;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
-
- import java.util.List;
-
- public class TeamMapperTest {
- private SqlSession sqlSession = MybatisUtil.getSqlSession();
-
- @Test
- public void testTeamMapper() {
- TeamMapper teamMapper = sqlSession.getMapper(TeamMapper.class);
- List
teams = teamMapper.queryAll(); - for (Team t : teams) {
- System.out.println(t);
- }
- }
- @Test
- public void testAddAfter(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- Team team = new Team();
- team.setTeamName("lxy");
- team.setLocation("shanghai");
- int i = mapper.addAfter(team);
- sqlSession.commit();
- System.out.println(i);
- System.out.println("新增id:"+team.getTeamId());
- }
-
- @Test
- public void teamTeamMapper(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- List
teams = mapper.queryByRange(1009, 1019); - teams.forEach(team -> System.out.println(team));
- }
- }
测试结果:
8.3.2 通过@Param注解(常用!!!)在方法的形参前面加入@Param("自定义参数名称"),mapper文件中使用#{自定义参数名称}的方式传参。
(1)TeamMapper接口添加如下内容:
List queryByRange2(@Param("min") Integer min, @Param("max") Integer max);
(2)TeamMapper.xml配置文件中添加如下:
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.TeamMapper">
-
- <select id="queryByRange2" resultType="com.lxy.pojo.Team">
- select * from team where teamId >=#{min} and teamId <=#{max};
- select>
- mapper>
(3)添加测试方法
- package com.lxy.test;
-
- import com.lxy.mapper.TeamMapper;
- import com.lxy.pojo.Team;
- import com.lxy.util.MybatisUtil;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
-
- import java.util.List;
-
- public class TeamMapperTest {
- private SqlSession sqlSession = MybatisUtil.getSqlSession();
-
- @Test
- public void teamTeamMapper2(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- List
teams = mapper.queryByRange2(1009, 1019); - teams.forEach(team -> System.out.println(team));
- }
- }
测试结果:

Map 集合可以存储多个值,使用Map向 mapper 文件一次传入多个参数。Map 集合使用 String的 key,Object 类型的值存储参数。 mapper 文件使用 # { key } 引用参数值
(1)TeamMapper接口添加如下内容:
List queryByRange3(Map map) ;
(2)TeamMapper.xml配置文件中添加如下:
- <select id="queryByRange3" resultType="com.kkb.pojo.Team">
- select * from team where teamId >=#{min} and teamId <= #{max};
- select>
(3)添加测试方法
- package com.lxy.test;
-
- import com.lxy.mapper.TeamMapper;
- import com.lxy.pojo.Team;
- import com.lxy.util.MybatisUtil;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
-
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- public class TeamMapperTest {
- private SqlSession sqlSession = MybatisUtil.getSqlSession();
-
- @Test
- public void teamTeamMapper3(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- Map
map = new HashMap<>(); - map.put("min",1009);
- map.put("max",1019);
- List
teams = mapper.queryByRange3(map); - teams.forEach(team -> System.out.println(team));
- }
- }
测试结果:
8.3.3 通过pojo类传递多个参数与map传递多个参数类似,要求映射文件中的参数占位符必须和pojo类中的属性完全一致。
(1)实体类:
- package com.lxy.pojo;
-
- public class QueryVO {
- private String name;
- private Integer min;
- private Integer max;
- private String location;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getMin() {
- return min;
- }
-
- public void setMin(Integer min) {
- this.min = min;
- }
-
- public Integer getMax() {
- return max;
- }
-
- public void setMax(Integer max) {
- this.max = max;
- }
-
- public String getLocation() {
- return location;
- }
-
- public void setLocation(String location) {
- this.location = location;
- }
- }
(2)TeamMapper接口添加如下内容:
List queryByCondition(QueryVO vo);
(3)TeamMapper.xml配置文件中添加如下:
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.TeamMapper">
-
-
- <select id="queryByCondition" resultType="com.lxy.pojo.Team">
- select * from team
- where teamId>=#{min} and teamId<=#{max}
- and teamName like #{name} and location=#{location}
- select>
-
- mapper>
(4)测试类添加方法:
- @Test
- public void testQueryByCondition(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- QueryVO vo = new QueryVO();
- vo.setLocation("北京");
- vo.setName("%球队%");
- vo.setMin(1001);
- vo.setMax(1020);
- List
teams = mapper.queryByCondition(vo); - teams.forEach(team -> System.out.println(team));
- }
测试结果:

#{}:表示一个占位符,通知Mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。这个是Mybatis 中的首选做法,安全迅速。
- <select id="queryById" parameterType="int" resultType="com.kkb.pojo.Team">
- select * from team where teamId=#{id}
- select>
${}:表示字符串原样替换,通知Mybatis 使用$包含的“字符串”替换所在位置。使用 Statement或者PreparedStatement 把 sql 语句和${}的内容连接起来。一般用在替换表名,
列名,不同列排序等操作。例如:根据球队名称,球队位置查询球队列表
示例:使用不同列作为查询条件
(1)TeamMapper接口添加如下内容:
List queryByFiled(@Param("column") String column,@Param("columnValue") String columnValue);
(2)TeamMapper.xml配置文件中添加如下:
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.TeamMapper">
-
- <select id="queryByFiled" resultType="com.lxy.pojo.Team">
- select * from team where ${column}=#{columnValue}
- select>
-
- mapper>
(3)添加测试方法
- package com.lxy.test;
-
- import com.lxy.mapper.TeamMapper;
- import com.lxy.pojo.QueryVO;
- import com.lxy.pojo.Team;
- import com.lxy.util.MybatisUtil;
- import org.apache.ibatis.session.SqlSession;
- import org.junit.Test;
-
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
-
- public class TeamMapperTest {
- private SqlSession sqlSession = MybatisUtil.getSqlSession();
-
- @Test
- public void testQueryByFiled(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- System.out.println("根据球队名称查询:");
- List
teams = mapper.queryByFiled("teamName","LALALA"); - teams.forEach(team -> System.out.println(team));
- System.out.println("根据球队位置查询:");
- List
teams2 = mapper.queryByFiled("location","北京"); - teams2.forEach(team -> System.out.println(team));
-
- }
- }
测试结果:
8.5 输出映射resultType: 执行 sql 得到 ResultSet 转换的类型,使用类型的完全限定名或别名。如果返回的是集合,设置的是集合元素的类型,而不是集合本身。resultType 和 resultMap,
不能同时使用。
案例:
(1)TeamMapper接口添加如下内容:
int getCount();
(2)TeamMapper.xml配置文件中添加如下:
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.TeamMapper">
-
-
- <select id="getCount" resultType="java.lang.Integer">
- select count(teamId) from team
- select>
-
- mapper>
(3)测试类添加方法:
- @Test
- public void testCount(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- int count = mapper.getCount();
- System.out.println("总共的行数:"+count);
- }

案例:参考之前的查询所有球队信息
List queryAll();
- <select id="queryAll" resultType="com.lxy.pojo.Team">
- select * from team;
- select>
当我们只需要查询表中几列数据的时候可以将sql的查询结果作为Map的key和value。一般使用的是Map
Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录会抛出TooManyResultsException异常。
如果有多行,使用List
案例:根据id查询球队名称和位置。
(1)TeamMapper接口添加如下内容:
- Map
- List
(2)TeamMapper.xml配置文件中添加如下:
- <select id="queryTwoColumn" resultType="java.util.HashMap">
- select teamName,location from team where teamId=#{id}
- select>
- <select id="queryTwoColumnList" resultType="java.util.HashMap">
- select teamName,location from team
- select>
(3)添加测试类
- @Test
- public void test08(){
- Map
map = teamMapper.queryTwoColumn(); - System.out.println(map);
- }
-
- @Test
- public void test09(){
- List
- for (Map
map : list) { - System.out.println(map);
- }
- }
测试结果:


resultType要求数据库中的列名和实体类中的保持一致
resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和 java 对象属性名不一样的情况。
(1)在TeamMapper接口中添加方法
List queryAll2();
(2)添加select节点,并定义 resultMap,指定列名和属性的对应关系
- <select id="queryAll2" resultMap="baseResultMap">
- select * from team;
- select>
-
- <resultMap id="baseResultMap" type="com.lxy.pojo.Team">
-
- <id column="teamId" property="teamId" javaType="java.lang.Integer" >id>
- <result column="teamName" property="teamName" javaType="java.lang.String">result>
- <result column="location" property="location" javaType="java.lang.String">result>
- <result column="createTime" property="createTime" javaType="java.util.Date">result>
- resultMap>
(3)添加测试方法
- @Test
- public void test10(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- List
teams = mapper.queryAll2(); - teams.forEach(team-> System.out.println(team));
- }
测试结果:

案例准备 创建表:
- use mybatis;
- DROP TABLE IF EXISTS `users`;
- CREATE TABLE `users` (
- `user_id` int NOT NULL AUTO_INCREMENT COMMENT '用户id',
- `user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户姓名',
- `user_age` int NULL DEFAULT NULL COMMENT '用户年龄',
- PRIMARY KEY (`user_id`) USING BTREE
- ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
- INSERT INTO `users` VALUES (1, '贾宝玉', 14);
- INSERT INTO `users` VALUES (2, '林黛玉', 13);
- INSERT INTO `users` VALUES (3, '薛宝钗', 15);
- SET FOREIGN_KEY_CHECKS = 1;
(1)创建实体类
- package com.kkb.pojo;
-
- public class Users {
- private Integer userId;
- private String userName;
- private Integer userAge;
-
- @Override
- public String toString() {
- return "Users{" +
- "userId=" + userId +
- ", userName='" + userName + '\'' +
- ", userAge=" + userAge +
- '}';
- }
-
- public Integer getUserId() {
- return userId;
- }
-
- public void setUserId(Integer userId) {
- this.userId = userId;
- }
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public Integer getUserAge() {
- return userAge;
- }
-
- public void setUserAge(Integer userAge) {
- this.userAge = userAge;
- }
- }
(2)创建UsersMapper接口
- public interface UsersMapper {
- Users queryByID(int userId);
- }
(3)映射文件UsersMapper.xml
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.UsersMapper">
-
- <select id="queryByID" resultType="com.lxy.pojo.Users">
- select user_id as userId,user_name as userName,user_age as userAge from users where user_id=#{id};
- select>
- mapper>
(4)编写测试类
- package com.lxy.test;
-
- import com.lxy.mapper.UsersMapper;
- import com.lxy.pojo.Users;
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
-
- public class TestUsersMapper {
- private UsersMapper usersMapper = MybatisUtil.getSqlSession().getMapper(UsersMapper.class);
-
- @Test
- public void test01(){
- Users users = usersMapper.queryByID(1);
- System.out.println(users);
- }
- }
测试结果:

(1)接口UsersMapper.java添加方法
Users queryByID2(int userId);
(2)映射文件UsersMapper.xml添加如下内容:
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.UsersMapper">
-
- <select id="queryByID" resultType="com.lxy.pojo.Users">
- select user_id as userId,user_name as userName,user_age as userAge from users where user_id=#{id};
- select>
-
-
- <select id="queryByID2" resultMap="baseMap">
- select * from users where user_id=#{id};
- select>
- <resultMap id="baseMap" type="com.lxy.pojo.Users">
- <id column="user_id" property="userId"/>
- <result column="user_name" property="userName"/>
- <result column="user_age" property="userAge"/>
- resultMap>
-
- mapper>
(3)测试类
- package com.lxy.test;
-
- import com.lxy.mapper.UsersMapper;
- import com.lxy.pojo.Users;
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
-
- public class TestUsersMapper {
- private UsersMapper usersMapper = MybatisUtil.getSqlSession().getMapper(UsersMapper.class);
-
- @Test
- public void test01(){
- Users users = usersMapper.queryByID(1);
- System.out.println(users);
- }
-
-
- @Test
- public void test02(){
- Users user = usersMapper.queryByID2(1);
- System.out.println(user);
- }
- }
测试结果:

案例中使用的 mybatis.xml就是Mybatis的全局配置文件。
全局配置文件需要在头部使用约束文件
- "1.0" encoding="UTF-8" ?>
- configuration
- PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-config.dtd">
MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息。 配置文档的顶层结构如下:
configuration(配置)
properties--属性:加载外部的配置文件,例如加载数据库的连接信息
Settings--全局配置参数:例如日志配置
typeAliases--类型别名
typeHandlers----类型处理器
objectFactory-----对象工厂
Plugins------插件:例如分页插件
Environments----环境集合属性对象
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
Mappers---映射器:注册映射文件用
属性可以在外部进行配置,并可以进行动态替换。我们既可以在 properties 元素的子元素中设置(例如DataSource节点中的properties节点),也可以在 Java 属性文件中配置这些属性。
数据源中有连接数据库的四个参数数据,我们一般都是放在专门的属性文件中,mybatis的全局配置文件直接从属性文件中读取数据即可。
(1)在 resources 目录创建 jdbc.properties 文件,文件名称可以自定义。
- jdbc.driver=com.mysql.cj.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
- jdbc.username=root
- jdbc.a=???
(2)mybatis的全局配置文件引入属性文件
<properties resource="jdbc.properties"/>
(3)使用属性文件中的值
- <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>
MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为.例如我们配置的日志就是应用之一。其余内容参考mybatis – MyBatis 3 | 配置
- <settings>
- <setting name="logImpl" value="LOG4J"/>
- settings>
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

9.4.2 自定义别名- <typeAliases>
-
- <typeAlias type="com.lxy.pojo.Team" alias="Team"/>
-
- <package name="com.lxy.pojo"/>
- typeAliases>
配置有多种方式:
- 语法:<mapper resource=""/>
-
- 使用相对于类路径的资源,从 classpath 路径查找文件
- 例如:<mapper resource="com/lxy/mapper/TeamMapper.xml" />
- 语法:<mapper class=""/>
-
- 使用的mapper接口的完全限定名
- 要求:接口和映射文件同包同名
- 例如<mapper class="com.lxy.mapper.GameRecordMapper"/>
- 语法:<package name=""/>
-
- 指定包下的所有Mapper接口
- 如:<package name="com.lxy.mapper"/>
- 注意:此种方法要求 Mapper接口名称和 mapper 映射文件名称相同,且在同一个目录中。
Mybatis 中访问数据库支持连接池技术,而且是采用的自己的连接池技术。在 Mybatis 的 mybatis.xml配置文件中,通过来实现 Mybatis 中连接池的配置。MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource。
Mybatis 的数据源分为三类:
UNPOOLED: 不使用连接池的数据源
POOLED:使用连接池的数据源
JNDI:使用JNDI实现的数据源
前两个数据源都实现javax.sql.DataSource接口
Mybatis 框架是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 Connection对象的 commit(), rollback() .Connection 对象的 setAutoCommit()方法来设置事务提交方式的。自动提交和手工提交、
<transactionManager type="JDBC"/>
该标签用于指定 MyBatis所使用的事务管理器。MyBatis 支持两种事务管理器类型:JDBC 与 MANAGED。
(1)JDBC:使用JDBC的事务管理机制,通过Connection对象的 commit()方法提交,通过rollback()方法 回滚。默认情况下,mybatis将自动提交功能关闭了,改为了手动提交,观察日志可以看出,所以我们在程序中都需要自己提交事务或者回滚事务。

(2)MANAGED:由容器来管理事务的整个生命周期(如Spring容器)。

SqlSessionFactory的openSession方法由重载,可以设置自动提交的方式。
如果sqlSession = SqlSessionFactory.openSession(true);参数设置为true,再次执行增删改的时候就不需要执行session.commit()方法,事务会自动提交。
表结构如图:

- package com.lxy.pojo;
-
- public class Player {
- private Integer playerId;
- private String playerName;
- private Integer playerNum;
- private Integer teamId;
- //多对一的体现:多方持有一方的对象 要有get方法
- private Team team1;//关联对象--多个球员可以属于同一个球队;
- private Team team2;//关联对象--多个球员可以属于同一个球队;
- private Team team3;//关联对象--多个球员可以属于同一个球队;
-
- public Integer getPlayerId() {
- return playerId;
- }
-
- public void setPlayerId(Integer playerId) {
- this.playerId = playerId;
- }
-
- public String getPlayerName() {
- return playerName;
- }
-
- public void setPlayerName(String playerName) {
- this.playerName = playerName;
- }
-
- public Integer getPlayerNum() {
- return playerNum;
- }
-
- public void setPlayerNum(Integer playerNum) {
- this.playerNum = playerNum;
- }
-
- public Integer getTeamId() {
- return teamId;
- }
-
- public void setTeamId(Integer teamId) {
- this.teamId = teamId;
- }
-
- public Team getTeam1() {
- return team1;
- }
-
- public void setTeam1(Team team1) {
- this.team1 = team1;
- }
-
- public Team getTeam2() {
- return team2;
- }
-
- public void setTeam2(Team team2) {
- this.team2 = team2;
- }
-
- public Team getTeam3() {
- return team3;
- }
-
- public void setTeam3(Team team3) {
- this.team3 = team3;
- }
-
- @Override
- public String toString() {
- return "Player{" +
- "playerId=" + playerId +
- ", playerName='" + playerName + '\'' +
- ", playerNum=" + playerNum +
- ", teamId=" + teamId +
- ", team1=" + team1 +
- ", team2=" + team2 +
- ", team3=" + team3 +
- '}';
- }
- }
- package com.lxy.mapper;
-
- import com.lxy.pojo.Player;
-
- public interface PlayerMapper {
- Player queryById(int playerId);
- Player queryById1(int playerId);
- Player queryById2(int playerId);
- Player queryById3(int playerId);
- }
要求:两表的连接查询
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.lxy.mapper.PlayerMapper">
-
- <resultMap id="baseResultMap" type="com.lxy.pojo.Player">
- <id column="playerId" property="playerId">id>
- <result column="playerName" property="playerName">result>
- <result column="playerNum" property="playerNum">result>
- <result column="teamId" property="teamId">result>
- resultMap>
-
- <select id="queryById1" resultMap="joinTeamResult1">
- select * from player p inner join team t
- on p.teamId=t.teamId where playerId=#{id}
- select>
- <resultMap id="joinTeamResult1" type="Player" extends="baseResultMap">
- <result column="teamId" property="team1.teamId">result>
- <result column="location" property="team1.location">result>
- <result column="teamName" property="team1.teamName">result>
- <result column="createTime" property="team1.createTime">result>
- resultMap>
- mapper>
编写测试类:
- package com.lxy.test;
-
- import com.lxy.mapper.PlayerMapper;
- import com.lxy.pojo.Player;
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
-
- public class TestPlayerMapper {
- PlayerMapper playerMapper= MybatisUtil.getSqlSession().getMapper(PlayerMapper.class);
-
- @Test
- public void test01(){
- Player player = playerMapper.queryById1(1);
- System.out.println(player);
- }
- }
测试结果:

要求:1、两表的连接查询
2、关联对象中已经存在被引用的resultMap
- <select id="queryById2" resultMap="joinTeamResult2">
- select * from player p inner join team t
- on p.teamId=t.teamId where playerId=#{id}
- select>
- <resultMap id="joinTeamResult2" type="Player" extends="baseResultMap">
- <association property="team2" javaType="Team"
- resultMap="com.lxy.mapper.TeamMapper.baseResultMap"/>
- resultMap>
测试类:
- package com.lxy.test;
-
- import com.lxy.mapper.PlayerMapper;
- import com.lxy.pojo.Player;
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
-
- public class TestPlayerMapper {
- PlayerMapper playerMapper= MybatisUtil.getSqlSession().getMapper(PlayerMapper.class);
-
- @Test
- public void test01(){
- Player player = playerMapper.queryById1(1);
- System.out.println(player);
- }
-
- @Test
- public void test02(){
- Player player = playerMapper.queryById2(1);
- System.out.println(player);
- }
- }
测试结果:

要求:1、不需要两表的连接查询
2、关联对象中已经存在被引用的查询方法
- <select id="queryById3" resultMap="joinTeamResult3">
- select * from player where playerId=#{id}
- select>
- <resultMap id="joinTeamResult3" type="Player" extends="baseResultMap">
- <association property="team3" javaType="Team"
- select="com.lxy.mapper.TeamMapper.queryById" column="teamId"/>
- resultMap>
测试类:
- package com.lxy.test;
-
- import com.lxy.mapper.PlayerMapper;
- import com.lxy.pojo.Player;
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
-
- public class TestPlayerMapper {
- PlayerMapper playerMapper= MybatisUtil.getSqlSession().getMapper(PlayerMapper.class);
-
- @Test
- public void test01(){
- Player player = playerMapper.queryById1(1);
- System.out.println(player);
- }
-
- @Test
- public void test02(){
- Player player = playerMapper.queryById2(1);
- System.out.println(player);
- }
-
- @Test
- public void test03(){
- Player player = playerMapper.queryById3(1);
- System.out.println(player);
- }
- }
测试结果:
10.2 对多关系的映射修改实体类Team.java:
- public class Team {
- private Integer teamId;
- private String teamName;
- private String location;
- private Date createTime;
- //一对多的体现:一方持有多方的对象
- private List
playerList1;//关联对象--一个球队可以拥有多个球员 - private List
playerList2;//关联对象--一个球队可以拥有多个球员
TeamMapper.java接口添加方法:
- public interface TeamMapper {
- Team queryById1(int teamId);
- Team queryById2(int teamId);
PlayerMapper.java接口中添加方法:
- public interface PlayerMapper {
- List
queryByTeamId(int teamId);
TeamMapper.xml添加:
- <select id="queryById1" resultMap="joinResult1">
- select * from team t join player p
- on t.teamId=p.teamId where t.teamId=#{id};
- select>
-
- <resultMap id="joinResult1" type="Team" extends="baseResultMap">
- <collection property="playerList1" javaType="java.util.ArrayList" ofType="player"
- resultMap="com.lxy.mapper.PlayerMapper.baseResultMap"/>
- resultMap>
添加测试类:
- @Test
- public void test11(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- Team team = mapper.queryById1(1001);
- System.out.println(team);
- }
测试结果:

10.2.2 方式2:引用关联对象的单独查询的方法
TeamMapper.xml添加:
- <select id="queryById2" resultMap="joinResult2">
- select * from team where teamId=#{id};
- select>
-
- <resultMap id="joinResult2" type="Team" extends="baseResultMap">
- <collection property="playerList2" javaType="java.util.ArrayList" ofType="player"
- select="com.lxy.mapper.PlayerMapper.queryByTeamId" column="teamId"/>
- resultMap>
PlayerMapper.xml添加如下内容:
- <select id="queryByTeamId" resultType="Player">
- select * from player where teamId=#{id}
- select>
测试类:
- @Test
- public void test12(){
- TeamMapper mapper = sqlSession.getMapper(TeamMapper.class);
- Team team = mapper.queryById2(1001);
- System.out.println(team);
- }
测试结果:
十一、动态SQL动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
之前学习过 JSTL,所以动态 SQL 元素会让你感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少
(1)原先的多条件查询做法
- /* 原有的多条件分析:都是通过java中的字符串拼接实现
- String sql="select * from team where 1 = 1 ";
- // 如果用户输入了名称,就模糊查询
- and teamName like '%?%'
- // 如果用户输入了日期,按照日期区间查询
- and createTime> ? and createTime< ?
- //如果输入了地区,按照地区查询
- and location =?";*/
-
- if(vo.getName()!=null && !"".equals(vo.getName().trim())){
- sql+=" and teamName like '%"+vo.getName().trim()+"%'";
- }
-
- if(vo.getBeginTime()!=null ){
- sql+=" and getEndTime>"+vo.getBeginTime();
- }
-
- if(vo.getBeginTime()!=null ){
- sql+=" and createTime<="+vo.getEndTime();
- }
-
- if(vo.getLocation()!=null && !"".equals(vo.getLocation().trim())){
- sql+=" and location ="+vo.getLocation().trim();
- }
(2)自己封装的查询条件类QueryTeamVO.java
- package com.lxy.pojo;
-
- import java.util.Date;
-
- public class QueryTeamVO {
- private String name;
- private Date beginTime ;
- private Date endTime;
- private String location;
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Date getBeginTime() {
- return beginTime;
- }
-
- public void setBeginTime(Date beginTime) {
- this.beginTime = beginTime;
- }
-
- public Date getEndTime() {
- return endTime;
- }
-
- public void setEndTime(Date endTime) {
- this.endTime = endTime;
- }
-
- public String getLocation() {
- return location;
- }
-
- public void setLocation(String location) {
- this.location = location;
- }
- }
(3)TeamMapper.java接口添加:
List queryByVO(QueryTeamVO vo);
(4)TeamMapper.xml映射文件添加:
-
- <select id="queryByVO" parameterType="QueryVO" resultMap="baseResultMap">
- select * from team
- <where>
-
- <if test="name!=null ">
- and teamName like concat(concat('%',#{name}),'%')
- if>
- <if test="beginTime!=null ">
- and createTime>=#{beginTime}
- if>
- <if test="endTime!=null ">
- and createTime<=#{endTime}
- if>
- <if test="location!=null ">
- and location=#{location}
- if>
- where>
- select>
(5)测试方法
- package com.lxy.test;
-
- import com.lxy.mapper.TeamMapper;
- import com.lxy.pojo.QueryTeamVO;
- import com.lxy.pojo.Team;
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
-
- import java.util.Date;
- import java.util.List;
-
- public class TestSql {
- private TeamMapper mapper = MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
-
- @Test
- public void test01(){
- QueryTeamVO vo = new QueryTeamVO();
- vo.setName("球");
- vo.setEndTime(new Date());
- vo.setLocation("北京");
- List
teams = mapper.queryByVO(vo); - teams.forEach(team -> System.out.println(team));
- }
- }
测试结果:

之前的做法如果没给其余属性赋值,那么null值会直接覆盖之前属性的值,所以并不合理
TeamMapper.java接口中的方法:
int update(Team team);
TeamMapper.xml映射文件对应的内容:
- <update id="update" parameterType="com.kkb.pojo.Team">
- update team set teamName=#{teamName},location=#{location},createTime=#{createTime}
- where teamId=#{teamId}
- update>
测试类中添加测试方法:
- @Test
- public void test2(){
- Team team=new Team();
- team.setTeamId(1055);
- team.setTeamName("lina");
- int update = teamMapper.update(team);
- MybatisUtil.getSqlSession().commit();
- System.out.println(update);
- }
测试结果:
11.2.2 使用set标签构建动态的SQL语句TeamMapper.java接口中添加方法:
int update1(Team team);
TeamMapper.xml映射文件对应的内容:
- <update id="update1" parameterType="com.lxy.pojo.Team">
- update team
- <set>
- <if test="teamName!=null">
- teamName=#{teamName}
- if>
- <if test="location!=null">
- location=#{location},
- if>
- <if test="createTime!=null">
- createTime=#{createTime},
- if>
- where teamId=#{teamId}
- set>
- update>
测试类:
- @Test
- public void test02(){
- Team team=new Team();
- team.setTeamId(1020);
- team.setTeamName("lina");
- int update = mapper.update1(team);
- MybatisUtil.getSqlSession().commit();
- System.out.println(update);
- }
测试结果:

TeamMapper.java接口中添加方法:
void addList(List list) ;
TeamMapper.xml映射文件对应的内容:
-
- <insert id="addList" parameterType="arrayList">
- insert into team (teamName,location) values
-
- <foreach collection="list" item="t" separator=",">
- (#{t.teamName},#{t.location})
- foreach>
- insert>
编写测试类:
- @Test
- public void test03(){
- List
list=new ArrayList<>(); - for(int i=1;i<=3;i++){
- Team team=new Team();
- team.setTeamName("lina"+i);
- team.setLocation("bj"+i);
- list.add(team);
- }
- mapper.addList(list);
- MybatisUtil.getSqlSession().commit();
- }
测试结果:
11.3.2 批量删除TeamMapper.java接口中添加方法:
void delList(List list) ;
TeamMapper.xml映射文件对应的内容:
- <delete id="delList" >
- delete from team where teamId in
-
-
-
- <foreach collection="list" item="teamId" separator="," open="(" close=")">
- #{teamId}
- foreach>
- delete>
编写测试类:
- @Test
- public void test04(){
- List
list = new ArrayList<>(); - list.add(1021);
- list.add(1022);
- list.add(1023);
- mapper.delList(list);
- MybatisUtil.getSqlSession().commit();
- }
测试结果:
十二、分页插件- <dependency>
- <groupId>com.github.pagehelpergroupId>
- <artifactId>pagehelperartifactId>
- <version>5.1.10version>
- dependency>
-
- <plugins>
- <plugin interceptor="com.github.pagehelper.PageInterceptor">
-
-
- plugin>
- plugins>
- @Test
- public void test5() {
- // PageHelper.startPage 必须紧邻查询语句,而且只对第一条查询语句生效
- PageHelper.startPage(2,5);
- List
teams = mapper.queryAll();//查询语句结尾不能有分号 - teams.forEach(team-> System.out.println(team));
- PageInfo
info=new PageInfo<>(teams); - System.out.println("分页信息如下:");
- System.out.println("当前页:"+info.getPageNum());
- System.out.println("总页数:"+info.getPages());
- System.out.println("前一页:"+info.getPrePage());
- System.out.println("后一页:"+info.getNextPage());
- System.out.println("navigatepageNums:"+info.getNavigatepageNums());
- for (int num : info.getNavigatepageNums()) {
- System.out.println(num);
- }
- }
测试结果:

PageInfo.java的部分源码:
- package com.github.pagehelper;
- import java.util.Collection;
- import java.util.List;
- /**
- * 对Page
结果进行包装 - *
- * 新增分页的多项属性,主要参考:http://bbs.csdn.net/topics/360010907
- *
- * @author liuzh/abel533/isea533
- * @version 3.3.0
- * @since 3.2.2
- * 项目地址 : http://git.oschina.net/free/Mybatis_PageHelper
- */
- @SuppressWarnings({"rawtypes", "unchecked"})
- public class PageInfo
extends PageSerializable { - //当前页
- private int pageNum;
- //每页的数量
- private int pageSize;
- //当前页的数量
- private int size;
- //由于startRow和endRow不常用,这里说个具体的用法
- //可以在页面中"显示startRow到endRow 共size条数据"
- //当前页面第一个元素在数据库中的行号
- private int startRow;
- //当前页面最后一个元素在数据库中的行号
- private int endRow;
- //总页数
- private int pages;
- //前一页
- private int prePage;
- //下一页
- private int nextPage;
- //是否为第一页
- private boolean isFirstPage = false;
- //是否为最后一页
- private boolean isLastPage = false;
- //是否有前一页
- private boolean hasPreviousPage = false;
- //是否有下一页
- private boolean hasNextPage = false;
- //导航页码数
- private int navigatePages;
- //所有导航页号
- private int[] navigatepageNums;
- //导航条上的第一页
- private int navigateFirstPage;
- //导航条上的最后一页
- private int navigateLastPage;
缓存是一般的ORM 框架都会提供的功能,目的就是提升查询的效率和减少数据库的压力。将经常查询的数据存在缓存(内存)中,用户查询该数据的时候不需要从磁盘(关系型数据库文件)上查询,而是直接从缓存中查询,提高查询效率,解决高并发问题。
MyBatis 也有一级缓存和二级缓存,并且预留了集成第三方缓存的接口。
Mybatis的缓存结构体系:

在操作数据库时需要构造 sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。
当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。
Mybatis默认开启一级缓存,存在内存中(本地缓存)不能被关闭,可以调用clearCache()来清空本地缓存,或者改变缓存的作用域。
工作原理图:

当用户发起第一次查询team=1001的时候,先去缓存中查找是否有team=1001的对象;如果没有,继续向数据中发送查询语句,查询成功之后会将teamId=1001的结果存入缓存中;
当用户发起第2次查询team=1001的时候,先去缓存中查找是否有team=1001的对象,因为第一次查询成功之后已经存储到缓存中,此时可以直接从缓存中获取到该数据,意味着不需要再去向数据库发送查询语句。
如果SqlSession执行了commit(有增删改的操作),此时该SqlSession对应的缓存区域被整个清空,目的避免脏读。前提:SqlSession未关闭。
测试:
- @Test
- public void test13(){
- Team t1=sqlSession.selectOne("com.lxy.mapper.TeamMapper.queryById",1001);//第一次查询,先查缓存,此时缓存中没有,继续向数据库发送查询语句
- System.out.println(t1);//查询完毕之后数据被自动存入缓存区域
- Team t2=sqlSession.selectOne("com.lxy.mapper.TeamMapper.queryById",1001);//第二次查询,因为缓存中已经有了该数据,可以直接获取,不需要发送查询语句
- System.out.println(t2);
- MybatisUtil.closeSqlSession();//关闭连接,缓存清空
- sqlSession=MybatisUtil.getSqlSession();//再次获取连接,此时缓存为空
- Team t3=sqlSession.selectOne("com.lxy.mapper.TeamMapper.queryById",1001);//新连接下第一次查询,肯定发送查询语句
- System.out.println(t3);//查询完毕之后数据被自动存入缓存区域
- int num=sqlSession.delete("com.lxy.mapper.TeamMapper.del",10000);
- sqlSession.commit();//提交之后缓存被整个清空
- System.out.println("删除结果:"+num);
- Team t4=sqlSession.selectOne("com.lxy.mapper.TeamMapper.queryById",1001);//第二次查询,因为缓存已经被上一次的提交清空了,所以还是需要发送查询语句
- System.out.println(t4);
- sqlSession.close();
- }
测试结果:


1、 session.clearCache( ) ;
2、 execute update(增删改) ;
3、 session.close( );
4、 xml配置 flushCache="true" ;
5、 rollback;
6、 commit。
多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace。
不同的sqlSession两次执行相同namespace下的sql语句参数相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。
Mybatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。
如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
二级缓存原理图:
13.3.1 使用二级缓存步骤 二级缓存是mapper范围级别的,默认不启用。
1、在Mybatis框架的全局配置文件中开启二级缓存

- <setting name="cacheEnabled" value="true"/>
2、在需要二级缓存的Mapper中添加缓存标志

3、实体类必须实现Serializable接口

4、测试二级缓存
如果两个session不是从同一个Factory获取,那么二级缓存将不起作用。
- @Test
- public void test2() {
- SqlSession sqlSession1 = MybatisUtil.getSqlSession();
- Team t1 = sqlSession1.selectOne("com.lxy.mapper.TeamMapper.queryById", 1001);//先查缓存,没有,先数据库,查询完毕写入二级缓存
- System.out.println(t1);
- MybatisUtil.closeSqlSession();//关闭连接,一级缓存清空,二级缓存存在
-
- SqlSession sqlSession2 = MybatisUtil.getSqlSession();
- Team t2 = sqlSession2.selectOne("com.lxy.mapper.TeamMapper.queryById", 1001);//先查缓存,有,直接获取,不需要查询数据库
- System.out.println(t2);
- MybatisUtil.closeSqlSession();//关闭连接,一级缓存清空,二级缓存存在
-
- SqlSession sqlSession3 = MybatisUtil.getSqlSession();
- int num = sqlSession3.delete("com.lxy.mapper.TeamMapper.del", 10000);//删除成功
- System.out.println("删除的结果:" + num);
- sqlSession3.commit();//提交之后清空二级缓存
- MybatisUtil.closeSqlSession();//关闭连接,缓存清空
-
- SqlSession sqlSession4 = MybatisUtil.getSqlSession();
- Team t3 = sqlSession4.selectOne("com.lxy.mapper.TeamMapper.queryById", 1001);先查缓存,曾经有,但是上一个提交已经清空了缓存,所以只能去数据库中查询,查询完毕写入二级缓存
- System.out.println(t3);
- MybatisUtil.closeSqlSession();//关闭连接,缓存清空
- }
对于变化比较频繁的SQL,可以禁用二级缓存。
在开始了二级缓存的XML中对应的statement中设置useCache=false禁用当前Select语句的二级缓存,意味着该SQL语句每次只需都去查询数据库,不会查询缓存。
useCache默认值是true。对于一些很重要的数据尽不放在二级缓存中。
- <cache>
- <property name="eviction" value="LRU"/>
- <property name="flushInterval" value="60000"/>
- <property name="size" value="1024"/>
- <property name="readOnly" value="true"/>
- cache>
源码:
- @Documented
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.TYPE)
- public @interface CacheNamespace {
- Class extends Cache> implementation() default PerpetualCache.class;
- Class extends Cache> eviction() default LruCache.class;
- long flushInterval() default 0;
- int size() default 1024;
- boolean readWrite() default true;
- boolean blocking() default false;
- Property[] properties() default {};
- }
-
- /**属性介绍:
- 1.映射语句文件中的所有select语句将会被缓存;
- 2.映射语句文件中的所有CUD操作将会刷新缓存;
- 3.缓存会默认使用LRU(Least Recently Used)算法来收回;
- 3.1、LRU – 最近最少使用的:移除最长时间不被使用的对象。
- 3.2、FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- 3.3、SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
- 3.4、WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
- 4.缓存会根据指定的时间间隔来刷新(默认情况下没有刷新间隔,缓存仅仅调用语句时刷新);
-
- 5.缓存会存储列表集合或对象(无论查询方法返回什么),默认存储1024个对象。
- 6.缓存会被视为是read/write(可读/可写)的缓存,意味着检索对象不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
- **/
如果想在命名空间中共享相同的缓存配置和实例,可以使用cache-ref 元素来引用另外一个缓存。
- <cache-ref namespace="com.lxy.mapper.TeamMapper" />
- //引用TeamMapper命名空间中的cache。
在pom.xml文件中的中中添加如下插件配置:
- <plugin>
- <groupId>org.mybatis.generatorgroupId>
- <artifactId>mybatis-generator-maven-pluginartifactId>
- <version>1.3.5version>
- <configuration>
-
- <configurationFile>src/main/resources/generatorConfig.xmlconfigurationFile>
- <overwrite>trueoverwrite>
- configuration>
- <dependencies>
- <dependency>
- <groupId>org.mybatis.generatorgroupId>
- <artifactId>mybatis-generator-coreartifactId>
- <version>1.3.5version>
- dependency>
- dependencies>
- plugin>
generatorConfig.xml内容:
其内容需要自己改一部分
- "1.0" encoding="UTF-8"?>
- generatorConfiguration
- PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
- "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
- <generatorConfiguration>
-
- <classPathEntry
- location="D:\repository\mysql\mysql-connector-java\8.0.23\mysql-connector-java-8.0.23.jar" />
- <context id="MyBatis" targetRuntime="MyBatis3">
-
- <commentGenerator>
- <property name="suppressAllComments" value="true" />
- commentGenerator>
-
- <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
- connectionURL="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT"
- userId="root"
- a="???">
- jdbcConnection>
-
- <javaTypeResolver>
- <property name="forceBigDecimals" value="false" />
- javaTypeResolver>
-
- <javaModelGenerator targetPackage="org.xzk.pojo"
- targetProject="src\main\java">
- <property name="trimStrings" value="true" />
- javaModelGenerator>
-
- <sqlMapGenerator targetPackage="org.xzk.mapper"
- targetProject="src\main\resources">
- sqlMapGenerator>
-
- <javaClientGenerator type="XMLMAPPER"
- targetPackage="org.xzk.mapper"
- targetProject="src\main\java">
- javaClientGenerator>
-
-
-
- <table tableName="team">
- <property name="useActualColumnNames" value="true"/>
- table>
- <table tableName="player">
- <property name="useActualColumnNames" value="true"/>
- table>
- <table tableName="gameRecord">
- <property name="useActualColumnNames" value="true"/>
- table>
- context>
- generatorConfiguration>
注意只能运行一次,运行完毕显示BUILD SUCCESS即为成功。

如果想重新生成,需要将之前生成的删除掉
1.使用时需要注意,生成后所使用的mapper需要在mybatis.xml中注册
2.使用时还需注意,如果其他数据库的表名和你需要生成的表名相同,那么你有可能会生成两个baseResultMap,使用时一点会报错
- package com.lxy.test;
-
- import com.lxy.util.MybatisUtil;
- import org.junit.Test;
- import org.xzk.mapper.TeamMapper;
- import org.xzk.pojo.Team;
- import org.xzk.pojo.TeamExample;
-
- import java.util.List;
-
- /**
- * 测试反向生成的内容
- */
- public class TestGenerator {
- private TeamMapper mapper = MybatisUtil.getSqlSession().getMapper(TeamMapper.class);
-
- @Test
- public void test1(){
- Team team = mapper.selectByPrimaryKey(1001);
- System.out.println(team);
- }
- @Test
- public void test2(){
- Team team = new Team();
- team.setTeamName("LALALA");
- team.setLocation("bjjj");
- int i = mapper.insertSelective(team);
- MybatisUtil.getSqlSession().commit();
- System.out.println(i);
- }
- @Test
- public void test3(){
- //理解为为多条件、排序等服务的类
- TeamExample example = new TeamExample();
- //理解为盛放条件的容器
- TeamExample.Criteria criteria = example.createCriteria();
- //向容器中添加条件
- criteria.andTeamNameLike("%队%");
- //criteria.andTeamIdBetween(1001,1020);
- example.setOrderByClause("teamId asc");
- List
teams = mapper.selectByExample(example); - for (Team team : teams) {
- System.out.println(team);
- }
- }
- }
如果你读到了这里,那请给博主点个攒吧!如果你有什么问题,可以在评论区留言,我会及时回答你。