0. ssm框架大纲

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1. Mybatis

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 第一个Mybatis程序mybatis-01

  • 搭建环境
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 CREATE DATABASE `mybatis`; USE `mybatis`; CREATE TABLE `user` ( `id` INT(20) 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')
  • 新建项目(创建子模块)

    • 配置mybatis的核心配置文件
    • 编写mybatis工具类
  • 编写实体类

    • 实体类
    • Dao接口
    • 接口实现类
  • 测试

    • junit测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # 错误1 org.apache.ibatis.binding.BindingException: Type interface com.xiaofan.dao.UserDao is not known to the MapperRegistry. # 解决方案 <mappers> <mapper resource="com/xiaofan/dao/UserMapper.xml"/> </mappers> # 错误2 Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com/xiaofan/dao/UserMapper.xml # 解决方案 <build> <resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> <include>**/*.tld</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> <include>**/*.tld</include> </includes> <filtering>true</filtering> </resource> </resources> </build>

在这里插入图片描述

  • 传递Map的情况
1 int addUser1(Map<String, Object> map);
1 2 3 4 <!-- map只要和键值保持一致即可 --> <insert id="addUser1" parameterType="map"> insert into mybatis.user (id, name, pwd) values(#{userId}, #{userName}, #{password}) </insert>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void testAddUser1() { SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("userId", 5); map.put("userName", "胡一刀"); map.put("password", "123456"); mapper.addUser1(map); // 增删改必须提交事务 sqlSession.commit(); sqlSession.close(); }
  • 模糊查询

    • Java代码执行的时候,传递通配符%%
    • 在拼接sql中拼接通配符!
    1 List<User> getUserLike(String value);
    1 2 3 <select id="getUserLike" resultType="com.xiaofan.pojo.User"> select * from mybatis.user where name like #{value} </select>
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Test public void testGetUserLike() { SqlSession sqlSession = null; try { sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUserLike("%胡%"); for (User user : userList) { System.out.println(user); } } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null) { sqlSession.close(); } } }

3. mybatis配置解析mybatis-02

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1 2 3 4 import org.apache.ibatis.type.Alias; @Alias(value = "hello") public class User {

在这里插入图片描述

在这里插入图片描述

4. 结果集映射(解决属性名和字段名不一致的情况)mybatis-03

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?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.xiaofan.dao.UserMapper"> <resultMap id="UserMap" type="User"> <!--column: 数据库中的字段 property: 实体字段--> <!--数据库字段和实体字段一样的就不用做处理--> <!--<result column="id" property="id" /> <result column="name" property="name" />--> <result column="pwd" property="password" /> </resultMap> <select id="getUserById" resultMap="UserMap"> select * from mybatis.user where id = #{id} </select> </mapper>

5. 日志mybatis-04

在这里插入图片描述

  • STDOUT_LOGGING标准日志

在这里插入图片描述

  • LOG4J

在这里插入图片描述

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 # 将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码 log4j.rootLogger=DEBUG,console,file # 配置CONSOLE输出到控制台 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout # 配置CONSOLE日志的输出格式 [frame] 2019-08-22 22:52:12,000 %r耗费毫秒数 %p日志的优先级 %t线程名 %C所属类名通常为全类名 %L代码中的行号 %x线程相关联的NDC %m日志 %n换行 log4j.appender.console.layout.ConversionPattern=[frame] %d{yyyy-MM-dd HH:mm:ss,SSS} - %-4r %-5p [%t] %C:%L %x - %m%n # 输出到日志文件中 log4j.appender.file=org.apache.log4j.RollingFileAppender # 保存编码格式 log4j.appender.file.Encoding=UTF-8 # 输出文件位置此为项目根目录下的logs文件夹中 log4j.appender.file.File=logs/root.log # 后缀可以是KB,MB,GB达到该大小后创建新的日志文件 log4j.appender.file.MaxFileSize=10MB # 设置滚定文件的最大值3 指可以产生root.log.1、root.log.2、root.log.3和root.log四个日志文件 log4j.appender.file.MaxBackupIndex=3 # 配置logfile为自定义布局模式 log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n # 输出日志级别(设置mybatis的日志级别) log4j.logger.org.mybatis=DEBUG # 对不同的类输出不同的日志文件 # com.xiaofan.dao包下的日志单独输出到xiaofan.log log4j.logger.com.xiaofan.dao=DEBUG,xiaofan # 设置为false该日志信息就不会加入到rootLogger中了 log4j.additivity.com.xiaofan.dao=false # 下面就和上面配置一样了 log4j.appender.xiaofan=org.apache.log4j.RollingFileAppender log4j.appender.xiaofan.Encoding=UTF-8 log4j.appender.xiaofan.File=logs/xiaofan.log log4j.appender.xiaofan.MaxFileSize=10MB log4j.appender.xiaofan.MaxBackupIndex=3 log4j.appender.xiaofan.layout=org.apache.log4j.PatternLayout log4j.appender.xiaofan.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %F %p %m%n

测试通过!

参考链接:https://www.cnblogs.com/zhangguangxiang/p/12007924.html

https://www.cnblogs.com/yidaxia/p/5820036.html

6. 分页 mybatis-04

7. Mybatis执行流程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

8. Lombok的使用(真正开发项目中不用)

  • idea 安装Lombok插件
  • 导包
  • 用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.xiaofan.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class Student { private String id; private String name; private int age; }

9 复杂查询环境搭建

注解和xml配合使用,对于简单的可以使用注解,复杂的使用xml

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 CREATE TABLE `teacher` ( `id` INT(10) NOT NULL PRIMARY KEY, `name` VARCHAR(30) DEFAULT NULL ) ENGINE=INNODB DEFAULT CHARSET=utf8; INSERT INTO teacher (`id`, `name`) VALUES (1, '秦老师'); 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; INSERT INTO `student` (`id`, `name`, `tid`) VALUES(1, '小明', 1); INSERT INTO `s`student`tudent` (`id`, `name`, `tid`) VALUES(2, '小红', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES(3, '小张', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES(4, '小李', 1); INSERT INTO `student` (`id`, `name`, `tid`) VALUES(5, '小王', 1);

9.1. 多对一mybatis-05

  • 按照嵌套查询进行处理(子查询)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <select id="getStudent1" resultMap="StudentTeacher1"> select * from mybatis.student; </select> <resultMap id="StudentTeacher1" type="Student"> <result property="id" column="id"/> <result property="name" column="name"/> <!--复杂的属性需要单独处理 对象:association 集合:collection--> <association property="teacher" column="tid" javaType="Teacher" select="getTeacherById"/> </resultMap> <select id="getTeacherById" resultType="Teacher"> select * from mybatis.teacher where id = #{id} </select>
  • 按照结果嵌套处理(多表关联)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <select id="getStudent2" resultMap="StudentTeacher2"> select s.id sid, s.name sname, t.name tname from student s, teacher t where s.tid = t.id </select> <!-- 注意别名问题 --> <resultMap id="StudentTeacher2" type="Student"> <result property="id" column="sid"/> <!-- 学生的名字 --> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <!-- 老师的名字--> <result property="name" column="tname"/> </association> </resultMap>

9.2. 一对多mybatis-06

  • 按照嵌套查询进行处理(子查询)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package com.xiaofan.dao; import com.xiaofan.pojo.Teacher; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; public interface TeacherMapper { @Select("select * from mybatis.teacher where id = #{id}") Teacher getTeacherById(@Param("id") int id); Teacher getTeacher1(@Param("tid") int id); }
1 2 3 4 5 6 7 8 9 10 11 <select id="getTeacher1" resultMap="TeacherStudent1"> select * from mybatis.teacher where id = #{tid} </select> <resultMap id="TeacherStudent1" type="Teacher"> <collection property="students" ofType="Student" javaType="ArrayList" select="getStudentByTeacherId" column="id"/> </resultMap> <select id="getStudentByTeacherId" resultType="Student"> select * from mybatis.student where tid = #{tid} </select>
  • 按照结果嵌套处理(多表关联)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <select id="getTeacher2" resultMap="TeacherStudent"> select s.id sid, s.name sname, t.id tid, t.name tname from student s, teacher t where s.tid = t.id and t.id = #{tid}; </select> <resultMap id="TeacherStudent" type="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname" /> <result property="tid" column="tid"/> </collection> </resultMap>

10. 动态Sqlmybatis-07

动态SQL就是指根据不同的条件生成不同的SQL语句

1 2 3 4 5 6 7 create table blog ( id varchar(50) not null comment '博客id', title varchar(100) not null comment '博客标题', author varchar(30) not null comment '博客作者', create_time datetime not null comment '创建时间', views int(30) not null comment '浏览量' ) ENGINE=InnoDB DEFAULT charset=utf8;
  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.xiaofan.dao; import com.xiaofan.pojo.Blog; import java.util.List; import java.util.Map; public interface BlogMapper { int addBlog(Blog blog); List<Blog> queryBlogIF(Map map); List<Blog> queryBlogChoose(Map map); int updateBlog(Map map); List<Blog> queryBlogForeach(Map map); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 <?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.xiaofan.dao.BlogMapper"> <insert id="addBlog" parameterType="blog"> insert into mybatis.blog (id, title, author, create_time, views) values (#{id}, #{title}, #{author}, #{createTime}, #{views}); </insert> <select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </where> </select> <select id="queryBlogChoose" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <choose> <when test="title != null"> title = #{title} </when> <when test="author != null"> and author = #{author} </when> <otherwise> and views = #{views} </otherwise> </choose> </where> </select> <update id="updateBlog" parameterType="map"> update mybatis.blog <set> <if test="title != null"> title = #{title}, </if> <if test="author != null"> author = #{author} </if> </set> where id = #{id} </update> <!-- select * from mybatis.blog where 1=1 and (id=1 or id=2 or id=3) --> <select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id = #{id} </foreach> </where> </select> </mapper>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 package com.xiaofan.dao; import com.xiaofan.pojo.Blog; import com.xiaofan.utils.IDUtils; import com.xiaofan.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Test; import java.util.*; public class MyTest { @Test public void testAddBlog() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Blog blog = new Blog(IDUtils.getId(), "Mybatis如此简单", "狂神说", new Date(), 9999); mapper.addBlog(blog); blog.setId(IDUtils.getId()); blog.setTitle("Java如此简单"); mapper.addBlog(blog); blog.setId(IDUtils.getId()); blog.setTitle("Spring如此简单"); mapper.addBlog(blog); blog.setId(IDUtils.getId()); blog.setTitle("微服务如此简单"); mapper.addBlog(blog); sqlSession.close(); } @Test public void queryBlogIF() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map<String, Object> map = new HashMap(); map.put("title", "Mybatis如此简单"); map.put("author", "狂神说"); mapper.queryBlogIF(map); sqlSession.close(); } @Test public void queryBlogChoose() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map<String, Object> map = new HashMap(); map.put("title", "Mybatis如此简单"); map.put("author", "狂神说"); map.put("views", 1000); mapper.queryBlogChoose(map); sqlSession.close(); } @Test public void updateBlog() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map<String, Object> map = new HashMap(); map.put("title", "Mybatis如此简单2"); // map.put("author", "狂神说"); map.put("id", "0d15b0c288514e39a8f757030a5708a9"); mapper.updateBlog(map); sqlSession.close(); } @Test public void queryBlogForeach() { SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); Map<String, Object> map = new HashMap(); List<Integer> ids = new ArrayList<Integer>(); ids.add(1); ids.add(2); ids.add(3); map.put("ids", ids); List<Blog> blogs = mapper.queryBlogForeach(map); for (Blog blog : blogs) { System.out.println(blog); } sqlSession.close(); } }

11. SQL片段

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!

  1. 使用sql标签抽取公共部分
1 2 3 4 5 6 7 8 <sql id="if-title_author"> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </sql>
  1. 在需要使用的地方使用include标签应用即可
1 2 3 4 5 6 <select id="queryBlogIF" parameterType="map" resultType="com.xiaofan.pojo.Blog"> select * from mybatis.blog <where> <include refid="if-title_author"/> </where> </select>

注意事项:

  1. 最好基于单标来定义sql片段
  2. 不要存在where标签

12. 缓存mybatis-08

  • 一级缓存(默认开启)

    • 开启日志

    • 测试在一个Session中查询两次相同的记录

    • 查看日志输出

    • 缓存失效的情况

      • 查询不同的东西
      • 增删改查操作,可能会改变原来的数据,所以必定会刷新缓存!
      • 查询不同的Mapper.xml
      • 手动清除缓存
  • 二级缓存

    在这里插入图片描述

    • 开启全局缓存
    1 <setting name="cacheEnabled" value="true"/>
    • 在当前Mapper中使用缓存
    1 2 <!-- 开启二级缓存 --> <cache />

    注意事项:实体需要序列化哦!

    在这里插入图片描述