MyBatis(二)
8 ResultMap(结果集映射)
resultMap用于替换resultType,在创建的实体类中的字段/属性名和数据库中的字段/属性名不一致的情况下使用。当实体类和数据库中的字段/属性名不一致时,SQL语句的查询结果会返回不一致的字段值为null,此时需要使用resultMap进行字段/属性名映射,使不一致的字段/属性名相互匹配,而非使用resultType。
8.1 resultType
resultType只是简单地将所有的列映射到HashMap的键上。即:
JavaBean(实体类)
package com.pojo;
public class User {
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String password() {
return password;
}
public void password(String password) {
this.password = password;
}
}
mybatis-config配置文件
<!-- SQL 映射 XML 中 -->
<select id="selectUsers" resultType="map">
select id, username, password
from some_table
where id = #{id}
</select>
MyBatis 会在幕后自动创建一个ResultMap,自动将列名与JavaBean中相同的属性名相互映射。即:
xml id username password
| | | |
| | | |
JavaBean id username password
如果列名和属性名没有精确匹配,可以在 SELECT 语句中对列使用别名(这是一个基本的 SQL 特性)来匹配标签。如下:
<select id="selectUsers" resultType="User">
select
user_id as "id",
user_name as "userName",
hashed_password as "password"
from some_table
where id = #{id}
</select>
8.2 resultMap
ResultMap可以自己在mybatis-config配置文件中使用resultMap标签进行配置,而不需要在SQL语句中对列使用别名。
<!--结果集映射-->
<resultMap id="userResultMap" type="User">
<!--property实体类中的属性,column数据库中的字段-->
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
<!--select标签中的resultMap通过上面resultMap标签中的id来选择指定-->
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
当只有部分字段不匹配时,只需配置部分字段的映射即可!
User{id,username,password}
DataBase{id,username,pwd}
mybatis-config.xml
<!--结果集映射-->
<resultMap id="userResultMap" type="User">
<!--property实体类中的属性,column数据库中的字段-->
<result property="password" column="pwd"/>
</resultMap>
<!--select标签中的resultMap通过上面resultMap标签中的id来选择指定-->
<select id="selectUsers" resultMap="userResultMap">
select id, username, pwd
from some_table
where id = #{id}
</select>
9 分页
9.1 Limit实现分页
MyBatis中使用limit实现分页只需要修改三个部分:Mapper接口、Mapper.xml配置文件以及测试类
- 在Mapper接口中定义方法
- 在Mapper.xml配置文件实现SQL语句
- 编写测试类
9.1.1 Mapper接口
在Mapper接口中定义方法
package com.dao;
import com.pojo.User;
import java.util.List;
import java.util.Map;
public interface UserMapper {
List<User> getUserByLimit(Map<String,Integer> map);
}
9.1.2 Mapper.xml配置文件
在Mapper.xml配置文件实现SQL语句
<select id="getUserByLimit" parameterType="map" resultType="com.pojo.User">
select * from mybatis.user limit #{startIndex}, #{size};
</select>
9.1.3 编写测试类
package com.dao;
import com.pojo.User;
import com.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserMapperTest {
@Test
public void getUserByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("startIndex",0);
map.put("size",2);
List<User> userList = mapper.getUserByLimit(map);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
9.2 RowBounds
狂神说Java—MyBatis—14.RowBounds分页
10 注解
对于简单的语句建议使用注解开发,但是对于复杂的语句还是使用xml配置文件配置!
10.1 自动提交事务
在工具类中设置自动提交事务
package com.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;
static{
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
}
10.2 使用注解实现CRUD(只针对简单的SQL语句)
只需要修改Mapper接口和测试类,甚至不需要Mapper.xml配置文件(但是mybatis-config配置文件仍旧需要,并且需要绑定接口!)
10.2.1 Mapper接口
package com.dao;
import com.pojo.User;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
import java.util.Map;
public interface UserMapper {
//查询所有学生
@Select("select * from user")
List<User> getUserList();
//根据学号查询学生
@Select("select * from user where id = #{id}")
User getUser(int id);
//根据学号删除学生
@Delete("delete from mybatis.user where id = #{id};")
void deleteUser(int id);
//插入一条学生信息
@Insert("insert into mybatis.user (id, name, pwd) values (#{id}, #{name}, #{pwd});")
void addUser(User user);
//更新一条学生信息
@Update("update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id};")
void updateUser(User user);
}
10.2.2 mybatis-config配置文件
<mappers>
<mapper class="com.dao.UserMapper"></mapper>
</mappers>
10.2.3 测试类
10.3 Lombok的使用
使用步骤:
-
在IDEA中添加Lombok的插件
File——>Settings——>Plugins——>搜索框搜索
-
在项目中导入Lombok的jar包(Maven)
<!--导入Lombok插件的jar包--> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency>
注意:
直接从Maven上复制的Lombok依赖为
<!--导入Lombok插件的jar包--> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency>
规定了作用域,删掉最后一句才能正常使用
-
在实体类上添加注解
package com.pojo; import lombok.Data; @Data @AllArgsConstructor @NoArgsConstructorpublic class User { private int id; private String name; private String pwd; }
使用上述三个注解可以无需再写构造函数、getter和setter方法以及toString方法!
11 复杂查询
本质:复杂的结果集映射
举例:一个老师有多个学生
对于学生而言,多个学生关联一个老师————>多对一,使用关联描述之间的关系(association)
对于老师而言,一个老师有多个学生的集合————>一对多,使用集合描述之间的关系(collection)
11.1 多对一处理
11.1.1 环境搭建
11.1.1.1 数据库建表
//创建teacher表
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
//插入一条teacher信息
INSERT INTO teacher(`id`,`name`) VALUES(1,'秦老师');
//创建student表,绑定外键为teacher的id
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
//插入5条学生信息
INSERT INTO student(`id`,`name`,`tid`) VALUES('1','xiaoming','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('2','xiaohong','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('3','xiaolan','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('4','xiaolv','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('5','xiaohuang','1');
11.1.1.2 新建项目
-
根据数据库表建立对应实体类
Student表
package com.pojo; import lombok.Data; @Data public class Student { private int id; private String name; //关联老师 private Teacher teacher; }
Teacher表
package com.pojo; import lombok.Data; @Data public class Teacher { private int id; private String name; }
-
编写对应Mapper接口
TeacherMapper
package com.dao; import com.pojo.Teacher; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface TeacherMapper { @Select("select * from teacher where id = #{id}") Teacher getTeacher(@Param("id") int id); }
StudentMapper
package com.dao; public interface StudentMapper { }
-
编写对应Mapper.xml文件
TeacherMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.TeacherMapper"> </mapper>
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.StudentMapper"> </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"> <configuration> <properties resource="db.properties"></properties> <typeAliases> <!-- <typeAlias type="com.pojo.User" alias="user"></typeAlias>--> <package name="com.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper class="com.dao.TeacherMapper"/> <mapper class="com.dao.StudentMapper"/> </mappers> </configuration>
-
编写测试类
测试是否可以查询到老师
import com.dao.TeacherMapper; import com.pojo.Teacher; import com.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; public class MyTest { public static void main(String[] args) { SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacher(1); System.out.println(teacher); sqlSession.close(); } }
11.1.1.2 需求解决
需求:查询所有的学生信息及对应老师的信息
SQL语句:select s.id,s.name,t.name from student s, teacher t where s.tid = t.id;
-
在对应Mapper类中编写需求方法
package com.dao; import com.pojo.Student; import java.util.List; public interface StudentMapper { //查询所有的学生信息及对应老师的信息 List<Student> getStudent(); }
-
编写对应Mapper.xml配置文件(StudentMapper.xml)
单纯的SQL语句好写,但是xml配置文件中不允许。
思路:
- 查询所有学生的信息
- 根据查询出来学生的tid寻找对应老师的信息
-
根据结果嵌套处理(推荐使用,较为简单)————对应MySQL中的联表查询
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.StudentMapper"> <select id="getStudent" resultMap="getStudentAndTeacher"> select s.id sid,s.name sname,t.name tname from student s, teacher t where s.tid = t.id; </select> <!--本质依旧为解决结果集映射问题--> <resultMap id="getStudentAndTeacher" type="Student"> <!--将Java类中的属性映射为对应数据库中的列名--> <result property="id" column="sid"/> <result property="name" column="sname"/> <!--复杂的属性单独处理 多对一的情况使用关联 association 一对多的情况使用集合 collection --> <association property="teacher" javaType="Teacher"> <!--teacher是一个类,类中的属性再映射--> <result property="name" column="tname"/> </association> </resultMap> </mapper>
-
根据查询嵌套处理————对应MySQL中的子查询
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.StudentMapper"> <!--方式一:根据查询嵌套查询,相当于子查询--> <select id="getStudent" resultMap="getStudentAndTeacher"> select * from student ; </select> <!--此时查出来的teacher一列为null,所以本质还是解决结果映射问题,即解决teacher属性映射--> <resultMap id="getStudentAndTeacher" type="Student"> <!--id:一般表示主键 result:万能(主键也可以) --> <result property="id" column="id"/> <!--上面写成<id property="id" column="id"/>也可以,因为是主键--> <result property="name" column="name"/> <!--复杂的属性单独处理 多对一的情况使用关联 association 一对多的情况使用集合 collection --> <association property="teacher" javaType="Teacher" column="tid" select="getTeacher"/> <!--teacher属性对应数据库中的tid列。 因为teacher属性是一个Java类,需要指定javaType。 然后用一个id为getTeacher的查询语句在teacher类中根据tid查询对应teacher信息--> </resultMap> <select id="getTeacher" resultType="Teacher"> select * from mybatis.teacher where id = #{tid}; </select> </mapper>
-
编写测试类
@Test public void testStudent(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); StudentMapper mapper = sqlSession.getMapper(StudentMapper.class); List<Student> studentList = mapper.getStudent(); for (Student student : studentList) { System.out.println(student); } sqlSession.close(); } /** Out: Student(id=1, name=xiaoming, teacher=Teacher(id=1, name=秦老师)) Student(id=2, name=xiaohong, teacher=Teacher(id=1, name=秦老师)) Student(id=3, name=xiaolan, teacher=Teacher(id=1, name=秦老师)) Student(id=4, name=xiaolv, teacher=Teacher(id=1, name=秦老师)) Student(id=5, name=xiaohuang, teacher=Teacher(id=1, name=秦老师)) **/
11.2 一对多处理
11.2.1 环境搭建
11.2.1.1 数据库建表
//创建teacher表
CREATE TABLE `teacher` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
//插入一条teacher信息
INSERT INTO teacher(`id`,`name`) VALUES(1,'秦老师');
//创建student表,绑定外键为teacher的id
CREATE TABLE `student` (
`id` INT(10) NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT(10) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8
//插入5条学生信息
INSERT INTO student(`id`,`name`,`tid`) VALUES('1','xiaoming','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('2','xiaohong','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('3','xiaolan','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('4','xiaolv','1');
INSERT INTO student(`id`,`name`,`tid`) VALUES('5','xiaohuang','1');
11.2.1.2 新建项目
-
根据数据库表建立对应实体类
Student表
package com.pojo; import lombok.Data; @Data public class Student { private int id; private String name; private int tid; }
Teacher表
package com.pojo; import lombok.Data; @Data public class Teacher { private int id; private String name; private List<Student> students; }
-
编写对应Mapper接口
TeacherMapper
package com.dao; import com.pojo.Student; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface TeacherMapper { @Select("select * from teacher") Teacher getTeacher(); }
StudentMapper
package com.dao; public interface StudentMapper { }
-
编写对应Mapper.xml文件
TeacherMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.TeacherMapper"> </mapper>
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.StudentMapper"> </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"> <configuration> <properties resource="db.properties"></properties> <typeAliases> <!-- <typeAlias type="com.pojo.User" alias="user"></typeAlias>--> <package name="com.pojo"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper class="com.dao.TeacherMapper"/> <mapper class="com.dao.StudentMapper"/> </mappers> </configuration>
-
编写测试类
测试是否可以查询到老师
import com.dao.TeacherMapper; import com.pojo.Teacher; import com.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; public class MyTest { public static void main(String[] args) { SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); List<Teacher> teacherList = mapper.getTeacher(); for(Teacher teacher : teacherList){ System.out.println(teacher); } sqlSession.close(); } }
11.2.2 需求解决
需求:查询指定老师下的所有学生及老师信息
SQL语句:select s.id sid,s.name sname,t.name tname,t.id tid from student s, teacher t where s.tid = t.id;
-
在对应Mapper类中编写需求方法
package com.dao; import com.pojo.Teacher; import java.util.List; public interface TeacherMapper { //查询所有的学生信息及对应老师的信息 List<Teacher> getTeacher(@Param("id") int id); }
-
编写对应Mapper.xml配置文件(TeacherMapper.xml)
单纯的SQL语句好写,但是xml配置文件中不允许。
思路:
- 查询所有学生的信息
- 根据查询出来学生的tid寻找对应老师的信息
-
根据结果嵌套处理(推荐使用,较为简单)————对应MySQL中的联表查询
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.TeacherMapper"> <select id="getTeacher" resultMap="TeacherStudent"> select s.id sid, s.name sname, t.name tname, t.id tid from mybatis.teacher t,mybatis.student s where s.tid = t.id and t.id = #{tid}; </select> <!--本质依旧为解决结果集映射问题--> <resultMap id="TeacherStudent" type="Teacher"> <result column="tid" property="id"/> <result property="name" column="tname"/> <!--复杂的属性单独处理 多对一的情况使用关联 association 一对多的情况使用集合 collection --> <!--集合中的泛型用ofType获取而不使用javaType--> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap> </mapper>
-
根据查询嵌套处理————对应MySQL中的子查询
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.TeacherMapper"> <select id="getTeacher2" resultMap="TeacherStudent2"> select * from mybatis.teacher where id = #{tid2}; </select> <select id="getStudentList" resultType="Student"> select * from mybatis.student where tid = #{tid2}; </select> <resultMap id="TeacherStudent2" type="Teacher"> <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentList" column="id"> </collection> </resultMap> </mapper>
-
编写测试类
@Test public void testTeacher(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacher(1); System.out.println(teacher); sqlSession.close(); } /** Out: Teacher(id=0, name=秦老师, students=[Student(id=1, name=xiaoming, tid=1), Student(id=2, name=xiaohong, tid=1), Student(id=3, name=xiaolan, tid=1), Student(id=4, name=xiaolv, tid=1), Student(id=5, name=xiaohuang, tid=1)]) **/
面试高频:
- MySQL引擎
- InnoDB底层原理
- 索引
- 索引优化
12 动态SQL
动态SQL:根据不同的条件生成不同的SQL语句
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
12.1 环境搭建
12.1.1 数据库环境搭建
CREATE TABLE `blog` (
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(100) NOT NULL COMMENT '博客作者',
`create_time` datetime NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8
12.1.2 创建项目
-
编写数据库对应的实体类
package com.pojo; import lombok.Data; import java.util.Date; @Data public class Blog { private String id; private int views; private String title; private String author; private Date createTime; //属性名和字段名不一致(数据库中是create_time) }
MyBatis中解决属性名和字段名不一致的方法:
在mybatis-config配置文件中的setting标签的mapUnderscoreToCamelCase属性为true
mapUnderscoreToCamelCase:是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射。默认为False。
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
开启之后可将数据库中的字段名create_time映射为Java类中的属性名createTime。
-
编写实体类对应的Mapper
package com.dao; public interface BlogMapper { }
-
编写Mapper对应的xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.dao.BlogMapper"> </mapper>
12.1.3 添加数据
-
编写实体类对应Mapper的方法
package com.dao; public interface BlogMapper { //插入数据 void addBlog(Blog blog); }
-
插入数据
//插入数据 @Test public void addTest(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Blog blog = new Blog(); blog.setId(IDUtils.getID()); blog.setAuthor("IU"); blog.setTitle("You And I"); blog.setCreateTime(new Date()); blog.setViews(10000); mapper.addBlog(blog); blog.setId(IDUtils.getID()); blog.setAuthor("IU"); blog.setTitle("Good Day"); blog.setCreateTime(new Date()); blog.setViews(12000); mapper.addBlog(blog); blog.setId(IDUtils.getID()); blog.setAuthor("IU"); blog.setTitle("Blueming"); blog.setCreateTime(new Date()); blog.setViews(10000); mapper.addBlog(blog); blog.setId(IDUtils.getID()); blog.setAuthor("IU"); blog.setTitle("BBIBBI"); blog.setCreateTime(new Date()); blog.setViews(10000); mapper.addBlog(blog); sqlSession.close(); }
12.2 trim(where、set)
-
where标签
-
set标签
12.3 if
if
12.4 choose···when···otherwise
choose···when···otherwise类似于Java中的switch···case···default语句
12.5 foreach
13 缓存
13.1 缓存简介
13.1.1 什么是缓存(Cache)
- 存在内存中的临时数据
- 将用户经常查询的数据存放在缓存(内存)中,用户查询数据时就不用从磁盘上(关系型数据库数据文件)查找,而是从缓存中查找,从而提高了查询效率。解决了高并发系统的性能问题
13.1.2 为什么使用缓存
- 减少和数据库的交互次数,减少系统开销,提高系统效率
13.1.3 什么样的数据适合使用缓存
- 经常查询且不经常改变的数据
13.2 MyBatis缓存
- MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制
- MyBatis系统默认定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存开启
- 一级缓存,基于SqlSession级别的缓存(随SqlSession的close而关闭),也称为本地缓存
- 二级缓存需要手动开启和配置,是基于namespace级别的缓存(在绑定接口中的所有方法中都可以使用)
- 为了提高可扩展性,MyBatis定义了缓存接口Cache。可以通过实现Cache接口来自定义二级缓存(也只能定义二级缓存)
13.2.1 一级缓存
-
一级缓存也叫做本地缓存:
- 与数据库同一次会话期间查询到的数据会放到本地缓存中
- 以后如果需要获取相同的数据,直接从缓存中拿,不必再查询数据库
-
一级缓存失效的情况:
-
查询不同的东西
-
增删改操作都会失效!(增删改操作会改变原来的数据,所以会刷新缓存)
-
查询不同的Mapper.xml
-
手动清理缓存(SqlSession有一个clearCache方法用来清理缓存)
SqlSession.clearCache();
-
13.2.2 二级缓存
- 二级缓存也叫全局缓存,由于一级缓存的作用域过低,所以诞生了二级缓存
- 基于namespace级别的缓存,一个名称空间对应一个二级缓存
- 工作机制
- 一个会话查询一条数据,这条数据就会被放在当前会话的一级缓存中
- 如果当前会话关闭了,这个会话对应的一级缓存也会消失。开启二级缓存后,一级缓存中的数据会放入二级缓存中
- 新的会话查询信息就可以从二级缓存中获取数据
- 不同的Mapper查出的数据会放在自己对应的缓存中
使用步骤:
-
开启全局缓存
在mybatis-config核心配置文件中使用setting标签
<!--开启全局缓存--> <settings> <setting name="cacheEnabled" value="true"/> </settings>
-
使用二级缓存
在Mapper.xml配置文件中添加cache标签
-
使用默认的二级缓存
<cache/>
-
使用配置的二级缓存
通过cache元素的属性来自配置二级缓存。
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/> <!--该配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的-->
-
可用的清除策略有:
- LRU – 最近最少使用:移除最长时间不被使用的对象。
- FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
- SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
- WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU
-
flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。
-
size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。
-
readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。
-
-
小结:
- 只要开启了二级缓存,在同一个Mapper下就有效
- 所有的数据会被先放在一级缓存中
- 只有当会话提交或会话关闭时,才会将一级缓存中的数据放入二级缓存中(将一级缓存中的数据转存入二级缓存)
13.2.3 自定义缓存(了解即可)
视频30
一般使用Redis!
13.2.4 MyBatis的缓存原理
执行SQL查询语句时:
- 先看二级缓存中有没有
- 再看一级缓存中有没有
- 最后再在数据库中查询