SSM - Mybatis - Syntax
1. Mybatis 简介
Mybatis 官网 @ mybatis – MyBatis 3 | 简介
Mybatis下载 GitHub @ GitHub - mybatis/mybatis-3: MyBatis SQL mapper framework for Java
Maven 仓库 @ Maven Repository: org.mybatis » mybatis (mvnrepository.com) , 其中POM修改如下:
<dependency> <!-- mysql驱动--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!-- mybatis--> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.13</version> </dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2. Mybatis 配置
涉及到的新文件:需要配置: POM.xml文件,resources/ mybatis-config.xml文件(定义MySQL数据库)/ UserMapper.xml文件(具体定义数据库访问接口规范)
如果遇到src/main/java/com/crevew/dao/*.xml 不打包的问题,有几种解决方案:
1. 把xml文件移到 resources目录下面,系统默认打包该文件夹下所有文件
2. 在POM.xml文件中增加以下配置,显示让maven打包;增加后,务必reload project,否则POM的修改不生效。(如果还不生效,就重启IDEA)
3. 可以在 target/classes/com/crevew/dao/ 下面核实该文件是否存在。
<build> <!--配置打包时不过滤非java文件开始 --> <!--说明,在进行模块化开发打jar包时,maven会将非java文件过滤掉, xml,properties配置文件等,但是这些文件又是必需的, 使用此配置可以在打包时将不会过滤这些必需的配置文件。 --> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>true</filtering> </resource> </resources> </build>
Mybatis Idea 编辑
Mybatis XML Idea编辑自动提示方法 (强烈推荐):@ (14条消息) IDEA Mybatis xml中配置sql代码自动提示【必看】_idea中xml如何设置自动提示_mingyuexinc的博客-CSDN博客
Mybatis plugin @ IDEA 添加 mybatis mapper的xml文件的自动提示功能 - 简书 (jianshu.com)
3. Mybatis 语法
Mybatis查询就直接查询;增删改需要提交事务。
Mybatis Mapper.xml 参数有三种类型:
1. Object,直接在sql取对象的属性即可
2. Map传递参数,直接在sql中取出属性,用于输出多个参数 (多个参数输入 用Map或者注解)
3. 基本类型(基本类型也可以不写)
模糊查询,可以在xml sql 当中拼接(不安全),也可以在代码执行的时候传递%%
select * from mybatis.user where name like #{value} 或者 List<User> userList = mapper.getUserLike("%李%");
#{} 预编译, ${} 无预编译
4. 配置解析
4.1 Mybatis 默认设置
默认的事务管理器是JDBC, 默认的连接池POOLED
4.2 Properties/typeAliases/Settings/Mappers
Properties: 可以通过properties属性来引用配置文件,如果配置db.properties之后,出现连接错误,原因是: @ 解决Mybatis报错:### Error querying database. Cause: java.sql.SQLException: No suitable driver found for_zhaiC_的博客-CSDN博客
typeAliases:
- 为Java类型设置一个短的名字(DIY),减少冗余;
- 也可以指定包名,Mybatis会自动搜索Java Bean,首字母小写;
- 在实体类较少时,使用前者;实体类较多的时候,使用后者; 但是后者不可以DIY,如果非要改,就在POJO上面增加注解实现@Alias()
Settings: logImpl, cacheEnabled, lazyLoadingEnabled 等。 (Plugin: mybatis-generator-core, mybatis-plus, 通用mapper)
Mappers 映射器: 通过 resource,class,file(不用),package,四种方式加载mapper
4.3 作用域和生命周期
SqlSessionFactoryBuilder: 一旦创建SqlSessionFactory,就不再需要了
SqlSessionFactory: 可以想象为数据库连接池,运行期一直存在,应用作用域;单例模式,或者静态单例模式
SqlSession: 连接到连接池的一个请求,用完需要关闭
5. 映射文件
5.1 ResultMap
解决属性名和字段名不一致的问题。问题是:数据库的字段名称,和pojo属性不一致。
方法一:别名
<select id="getUserById" parameterType="int" resultType="UserAlias"> select id,name,pwd as password from mybatis.user where id = #{id} </select>
方法二:ResultMap 结果集映射
6. 日志
logImpl: 重点是LOG4J, STDOUT_LOGGING
LOG4J 配置文件设置 @ (15条消息) LOG4J的配置文件_log4j配置文件_小逗比iswho的博客-CSDN博客
7. 分页
1. 使用SQL语句的limit实现分页,比如:select * from mybatis.user limit 1,2
2. 使用RowBounds分页,比如
//通过RowBounds实现 RowBounds rowBounds = new RowBounds(1, 2); //通过Java代码层面实现分页 List<User> userList = sqlSession.selectList("com.crevew.dao.UserMapper.getUserByRowBounds",null, rowBounds);
3. 分页插件: MyBatis PageHelper
8. 注解开发
关于接口的理解:
- 接口从更深层次的理解,应是定义(规范、约束)与实现(名实分离的原则)的分离。
- 接口的本身反映了系统设计人员对系统的抽象理解。
- 接口应有两类:第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface)。
- 一个个体可能有多个抽象面。抽象体与抽象面是有区别的。
三个面向区别
- 面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法。
- 面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现。
- 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题。更多的体现就是对系统整体架构。
注解和XML配置,可以同时使用。 注解的使用方法就是:在接口上实现。
- 本质:反射机制实现。
- 底层:动态代理。
9. Lombok
Lombok安装方式有三部,IDEA安装,POM引用,接口使用。详见 @ (15条消息) idea中怎么使用lombok依赖_idea依赖树只有lombok_南商的博客-CSDN博客
10. 多对一处理
实验环境搭建: @ (15条消息) Mybatis一对多,多对一_mybatis一对多 多对一_羊村跳水冠军个人学习笔记的博客-CSDN博客
方法一:按照查询嵌套处理,相当于子查询
1. 查询所有的学生信息;
2. 根据查询出来的学生id,寻找对应的老师,子查询
3. -->
<select id="getStudent" resultMap="StudentTeacher"> select * from student </select> <resultMap id="StudentTeacher" type="Student"> <result property="id" column="id"/> <result property="name" column="name"/> <!--复杂的属性,我们需要单独处理. 对象: association; 集合: collection --> <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/> </resultMap> <select id="getTeacher" resultType="Teacher"> select * from teacher where id=#{id} </select>
方法二:按照结果嵌套处理,相当于连表查询
<select id="getStudent2" resultMap="StudentTeacher2"> select s.id sid, s.name sname, t.name tname, t.id tid 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"/> <result property="id" column="tid"/> </association> </resultMap>
11. 一对多处理
方法一:按照查询嵌套处理
<!--按照查询进行--> <select id="getTeacher2" resultMap="TeacherStudent2"> select * from mybatis.teacher where id=#{tid} </select> <resultMap id="TeacherStudent2" type="Teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/> </resultMap> <select id="getStudentByTeacherId" resultType="Student"> select * from mybatis.student where tid=#{id} </select>
方法二:按照结果嵌套处理
<!--按照结果查询--> <select id="getTeacher" resultMap="TeacherStudent"> select s.id sid, s.name sname, t.name tname, t.id tid 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"/> <!-- 对象association; 集合collection 集合中的泛型信息,我们使用ofType获得--> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap>
小结:
- 关联--- association
- 集合---collection
- javaType 用来指定实体类中属性的类型
- ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型!
12. 动态SQL
动态SQL就是根据不同的条件生成不同的SQL语句. 所谓的动态SQL,本质还是SQL语句, 只是在SQL层面,去执行一个逻辑代码
主要关键词: if (test), choose (when, otherwise), trim (where, set), foreach
动态SQL就是拼接SQL,一般建议在MySQL中写出完整的SQL,再对应修改相应的动态语句。
SQL片段,相当于SQL函数 (最好基于单标,最好不要存在where标签等)
<sql id="if-title-author"> <if test="title != null"> title = #{title}, </if> <if test="author != null"> author = #{author} </if> </sql> <insert id="updateBlog" parameterType="Blog"> update mybatis.blog <set> <include refid="if-title-author"/> </set> </insert>
13. 缓存
一级缓存,默认开启,无法关闭,只在一次SqlSession中有效。
二级缓存,手动开启
- 二级缓存,也叫全局缓存;一级缓存作用域太低了,所以诞生了二级缓存。
- 基于namepsace级别的缓存,一个名称空间,对应一个二级缓存;
- 只要开启二级缓存,需要序列化
- 工作机制是:
- 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
- 如果当前会话关闭了,这个会话对应的一级缓存就没有了,但是我们想要的是,即使会话关闭,一级缓存的数据被保存到二级缓存中。
- 新的会话查询信息,就可以从二级缓存中获取内容。
- 不同的mapper查出的数据会被放在自己对应的缓存中。
第三方缓存:ehcache 是一个Java缓存机制,早期在Hibernate里使用后。现在,一般都是使用Redis作为缓存。
附录
Teacher/Student表
CREATE TABLE `teacher` (
`id` INT NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4;
INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老师');
CREATE TABLE `student` (
`id` INT NOT NULL,
`name` VARCHAR(30) DEFAULT NULL,
`tid` INT DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fktid` (`tid`),
CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)
) ENGINE=INNODB DEFAULT CHARSET=UTF8MB4;
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`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');
博客表
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客ID',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`auther` VARCHAR(30) NOT NULL COMMENT '博客作者',
`creat_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=UTF8MB4
浙公网安备 33010602011771号