Mybatis
1、简介
1.1 什么是Mybatis
-
MyBatis 是一款优秀的持久层框架,
-
它支持自定义 SQL、存储过程以及高级映射。
-
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集
-
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
1.2 如何获得Mabatis
-
maven仓库:
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.16</version> </dependency>
1.3 持久化
数据持久化: 将程序的数据在持久状态和瞬时状态转化的过程
为什么需要持久化: 某些对象不能丢掉,内存贵
1.4 持久层
Dao层,Service层,Controller层
-
完成持久化工作的代码块
-
层界限十分明显
1.4 为什么需要Mabatis
-
把数据存入数据库
-
方便
-
简化JDBC,自动化
-
技术没有高低之分
-
优点
-
简单易学
-
sql和代码分离,提高了可维护性
-
提供xml标签,支持编写动态sql
-
2、第一个Mybatis程序
搭建环境-->导入Mybatis-->编写代码-->测试
2.1 搭建环境
搭建数据库
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,'fys','000000'), (3,'twd','888888')
新建项目
1.新建一个普通的maven项目
2.删除src
3.导入maven依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.twd</groupId> <artifactId>Mybatis-Study</artifactId> <version>1.0-SNAPSHOT</version> <!-- 导入依赖--> <dependencies> <!-- mysql--> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <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.16</version> </dependency> <!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies> <name>Archetype - Mybatis-Study</name> <url>http://maven.apache.org</url> </project>
2.2创建一个模块
-
编写mybatis的核心配置文件
<?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/mybatis?useSSL=true&userUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="@twd20040401."/> </dataSource> </environment> </environments> </configuration>
-
编写mybatis工具类
package com.twd.dao.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 { //获取sqlSessionFactory对象 String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { throw new RuntimeException(e); } } //SqlSession完全包含了面向数据库执行SQL命令所需所有方法 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
2.3编写代码
-
实现类
package com.twd.pojo; import java.util.Stack; public class User { private int id; private String name; private String pwd; public User(int id, String name, String pwd) { this.id = id; this.name = name; this.pwd = pwd; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
-
Dao接口
public interface UserDao { List<User> getUserList(); }
-
接口实现类 由原来的UserDaoImp转变为Mapper配置文件
<?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.twd.dao.UserDao"> <select id="getUserList" resultType="com.twd.pojo.User"> select * from mybatis.user </select> </mapper>
2.4 测试
MapperRegistry是什么?
核心配置文件中注册mappers
junit测试
package com.twd.dao; import com.twd.pojo.User; import com.twd.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import java.util.List; public class UserDaoTest { @Test public void test(){ //第一步获取sqlSession对象 SqlSession sqlSession = MybatisUtils.getSqlSession(); //第二部执行sql UserDao mapper = sqlSession.getMapper(UserDao.class); List<User> userList = mapper.getUserList(); for (User user : userList) { System.out.println(user); } //关闭sqlsession sqlSession.close(); } }
3、CRUD
1.namespace:
namespace中的包名要和Dao/mapper接口的包名一致
2.selece:
查询语句 <select id="getUserList" resultType="com.twd.pojo.User">
-
id:对应namespace中的方法名
-
resultType:sql语句执行的返回值
-
parameterType
3.Insert update delete
3.1 编写接口
public interface UserMapper { //查询全部用户 List<User> getUserList(); //根据id查询用户 User getUserById(int id); // insert一个用户 Integer addUser(User user); //修改用户 Integer updateUser(User user); //删除用户 Integer deleteUser(int id); }
3.2编写对应的mapper中的sql
<!--对象中的属性可以直接取出来--> <select id="addUser" resultType="com.twd.pojo.User" > insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd}); </select> <select id="updateUser" resultType="com.twd.pojo.User"> update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}; </select> <select id="deleteUser" resultType="com.twd.pojo.User"> delete from mybatis.user where id =#{id}; </select>
3.3测试
//增删改需要提交事务 @Test public void addUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Integer i = mapper.addUser(new User(8, "卡米", "123123")); //提交事务 sqlSession.commit(); sqlSession.close(); } @Test public void updateUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.updateUser(new User(5,"qwer","123000")); sqlSession.commit(); sqlSession.close(); } @Test public void deleteUser(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Integer i = mapper.deleteUser(6); sqlSession.close(); }
4.万能的Map
假设我们的实体类,或者数据库中的表,字段或参数过多,我们应当考虑使用Map
Integer addUser2(Map<String, Object> map);
<!--对象中的属性可以直接取出来 传递map的key--> <select id="addUser2" parameterType="map"> insert into mybatis.user (id,name,pwd) values (#{userid},#{username},#{password}); </select>
@Test public void addUser2(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String,Object> map=new HashMap<String, Object>(); map.put("userid",10);//User姓名未包含 map.put("password",111111111); mapper.addUser2(map); sqlSession.close(); }
Map传递参数,直接在sql中取出key即可【parameterType="map"】
对象传递参数,直接在sql中取出对象的属性即可【parameterType="Object"】
只有一个基本类型参数情况下,可以直接在sql中取到 可省略parameterType
多个参数用Map,或者注解
模糊查询
<select id="getUserLike" resultType="com.twd.pojo.User"> select * from user where name like #{value} </select>
List<User> userLike = mapper.getUserLike("%迪%");
4、配置解析
4.1 核心配置文件
-
mybatis-config.xml
-
MyBatis的配置文件包含了会深深影响MyBatis行为的设置和属性信息
configuration(配置) properties(属性) settings(设置) typeAliases(类型别名) typeHandlers(类型处理器) objectFactory(对象工厂) plugins(插件) environments(环境配置) environment(环境变量) transactionManager(事务管理器) dataSource(数据源) databaseIdProvider(数据库厂商标识) mappers(映射器)
4.2 环境配置(environments)
mybatis可以配置成适应多种环境
但是尽管可以配置多个环境,每个SqlSessionFactory实例只能选择一种环境
Mybatis默认事务管理器就是JDBC,连接池:POOLED
4.3 属性(properties)
我们可以通过properties属性来实现引用配置文件
这些属性都是可外部配置且动态替换的,既可以在典型的java属性文件中配置,亦可通过properties元素的子元素来传递。【db.properties】
编写一个配置文件
db.properties
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&userUnicode=true&characterEncoding=UTF-8 username=你的用户名 password=你的密码
4.4 别名(typeAliases)
-
类型别名是为java类型设置一个短的名字
-
存在的意义仅在于用来减少类完全限定名的冗余
<!-- 可以给实体类起别名--> <typeAliases> <typeAlias type="com.twd.pojo.User" alias="User"/> </typeAliases>
也可以指定一个包名,MyBatis会在包名下面搜索需要的java Bean,比如:
扫描实体类的包,他的默认别名就为这个类的别名,首字母小写
<typeAliases> <package name="com.twd.pojo"/> </typeAliases>
在实体类比较少的时候用第一种,
实体类很多就用第二种
第一种可以DIY,第二种“不行”,如果非要改,就要在实体类加上注解
4.5 设置(settings)
Mybatis中极为重要的调整设置,他会改变MyBatis的运行时行为
4.6 其他配置
-
typeHandlers(类型处理器)
-
objectFactory(对象工厂)
-
plugins插件
-
mybatis-generator
-
mybatis-plus
-
通用mapper
-
4.7 映射器(mappers)
MapperRegitry:注册绑定我们的Mapper文件
<mappers> <!-- <mapper resource="com/twd/dao/UserMapper.xml"/>--> <mapper class="com.twd.dao.UserMapper"/> </mappers>
使用class:
-
接口和他的Mapper配置文件必须同名
-
接口和他的Mapper配置文件必须在同一个 包下
4.7 作用域(Scope)和生命周期
不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder
-
一旦创建了SqlSessionFactory,就不再需要他了
-
局部变量
SqlSessionFactory
-
可以理解为:数据库连接池
-
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例
-
因此SqlSessionFactory的最佳作用域是应用作用域
-
最简单的就是单例模式或静态单例模式
Session
-
连接到连接池的一个请求
-
SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域
-
用完之后就关闭它
5、解决属性名和字段名不一致的问题
5.1 ResultMap
<resultMap id="UserMap" type="User"> <result column="id" property="id"/> <result column="name" property="name"/> <result column="pwd" property="password"/> </resultMap> <select id="getUserById" parameterType="int" resultMap="UserMap" > select * from mybatis.user where id = #{id} </select>
把数据库字段名与应用属性名做结果集映射
-
result Map元素是MyBatis中最重要最强大的元素
-
ResultMap的设计思想是,对于简单的语句根本不需要配置显示的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了
如果世界总是如此简单就好了
6、日志
6.1 日志工厂
如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的助手
以前:debug
现在:日志工厂
-
SLF4J
-
LOG4J 【掌握】
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING 【掌握】
-
NO_LOGGING
在Mybatis中具体使用哪一个日志实现,在设置中设定
STDOUT_LOGGING标准日志输出
<setting name="logImpl" value="STDOUT_LOGGING"/>
6.2 Log4j
什么是log4j
-
Log4j是Apache的一个开源项目,通过使用log4j,我们就可以控制日志信息输送的目的地是控制台,文件,GUI组件
-
我们也可以控制每一条日志的输出格式
-
通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程
-
通过一个配置文件来灵活地进行配置,而不是需要修改应用的代码
1.先到日log4j的包
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
2.创建log4j.properties
#将等级为DEBUG的日志信息输出到console和file两个目的地 log4j.rootLogger=DEBUG,console,file #控制台输出的相关设置 log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Target=System.out log4j.appender.console.Threshold=DEBUG log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern=[%c]-%m%n #文件输出的相关配置 log4j.appender.file=org.apache.log4j.RollingFileAppender log4j.appender.file.File=./log/kuang.log log4j.appender.file.MaxFileSize=10mb log4j.appender.file.Threshold=DEBUG log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}[%c]%m%n #日志输出级别 log4j.logger.org.mybatis=DEBUG log4j.logger.java.sql=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.ResultSet=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG
3.配置log4j为日志的实现
<settings> <setting name="logImpl" value="LOG4J"/> </settings>
4.log4j的使用,直接测试运行
简单使用
-
导包import org.apache.log4j.Logger;
-
日志对象,参数为当前类的class
static Logger logger=Logger.getLogger(UserDaoTest.class);
-
日志级别
logger.info("info:进入了testLog4j"); logger.debug("debug:进入了testLog4j"); logger.error("error:进入了testLog4j");
7、分页
分页的最用就是减少处理量
使用limit分页
SELECT * FROM `user` LIMIT 3,2
选择从第4个开始后面2个
1.接口
List<User> getUserByLimit(HashMap<String, Object> map);
2.Mapper.xml
<select id="getUserByLimit" parameterType="map" resultMap="UserMap"> select * from mybatis.user limit #{startIndex},#{pageSize} </select>
3.测试
@Test public void getUserByLimit(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("startIndex",0); map.put("pageSize",2); List<User> userByLimit = mapper.getUserByLimit(map); for (User user : userByLimit) { System.out.println(user); } sqlSession.close(); }
8、使用注解开发
1.注解在接口上实现
@Select("select * from user") List<User> getUsers();
2.需要在核心配置文件中绑定接口
<!--绑定接口--> <mappers> <mapper class="com.twd.dao.UserMapper"/> </mappers>
3.测试
本质:反射机制实现
底层:动态代理模式
Mybatis详细执行过程
8.1 使用注解实现CRUD
编写接口
public interface UserMapper { @Select("select * from user") List<User> getUsers(); //有多个参数要加上@param注解 @Select("select * from user where id=#{id}") User getUserById(@Param("id") int id); @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})") Integer addUser(User user); @Update("update user set name=#{name},pwd=#{password} where id=#{id}") Integer updateUser(User user); @Delete("delete from user where id=#{uid}") Integer deleteUser(@Param("uid") int id); }
测试类
【注意:必须将接口注册绑定到我们的核心配置文件中】
关于@Param()注解
-
基本类型的参数或者Sring类型,需要加上
-
引用类型不需要加
-
如果只有一个基本类型的话,可以忽略,但还是建议加上
-
我们在sql中引用的就是我们这里的@Param()中设定的属性名
#{} ${}的区别
#{}很大程度防止sql注入
${}无法防止,不安全
9、Lombok
偷懒专用
1.IDEA里下载插件,直接搜lombok
2.导入maven
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.32</version> <scope>provided</scope> </dependency>
@Getter and @Setter @FieldNameConstants @ToString @EqualsAndHashCode @AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor @Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger, @CustomLog @Data @Builder @SuperBuilder @Singular @Jacksonized @Delegate @Value @Accessors @Tolerate @Wither @With @SneakyThrows @StandardException @val @var experimental @var @UtilityClass Lombok config system Code inspections Refactoring actions (lombok and delombok)
常用的
@Data @AllArgsConstructor @NoArgsConstructor @ToString @Getter
10、多对一处理
对于学生而言:n个学生对应一个老师(关联)
对于老师而言:一个老师教多个学生(集合)
CREATE TABLE `teacher` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, PRIMARY KEY (`id`) ) 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 `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');
10.1 测试环境搭建
-
导入lombok
-
新建实体类Teacher,Student
package com.twd.pojo; import lombok.Data; @Data public class Teacher { private int id; private String name; }
@Data public class Student { private int id; private String name; // 学生需要关联一个老师 private Teacher teacher; }
-
建立Mapper接口
public interface TeacherMapper { @Select("select * from teacher where id=#{tid}") Teacher getTeacher(@Param("tid") int id); }
-
建立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.twd.dao.TeacherMapper"> </mapper>
-
在核心配置文件中绑定注册我们的Mapper
<!--绑定接口--> <mappers> <mapper class="com.twd.dao.StudentMapper"/> <mapper class="com.twd.dao.TeacherMapper"/> <!-- <mapper resource="com/twd/dao/*Mapper.xml"/>--> </mappers>
-
测试查询是否成功
@Test public void getTeacher(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class); Teacher teacher = mapper.getTeacher(1); System.out.println(teacher); sqlSession.close(); }
10.2 按照查询嵌套处理
<!-- 1.获取全部的学生信息 2.根据查询出来的学生id找老师--> <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>
10.3 按照结果嵌套处理
<!--按照结果嵌套处理--> <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" column="Teacher"> <result property="name" column="tname"/> </association> </resultMap>
11、一对多处理
1.搭建环境,跟刚才一样
实体类
@Data public class Teacher { private int id; private String name; // 一个老师有多个学生 private List<Student> students; } @Data public class Student { private int id; private String name; private int tid; }
按照结果处理
<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"/> <!-- javaType 指定的属性的类型 集合中的泛型信息,我们使用ofType获取--> <collection property="students" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap>
按照查询嵌套
<select id="getTeacher2" resultMap="TeacherStudent2"> select * from teacher where id=#{tid} </select> <resultMap id="TeacherStudent2" type="Teacher"> <collection property="students" javaType="Arraylist" ofType="Student" select="getStudentByTeacherId" column="id"/> </resultMap> <select id="getStudentByTeacherId" resultType="Student"> select * from student where tid=#{id} </select>
小结
1.关联-association【多对一】
2.集合-collection【一对多】
3.javaType & ofType
-
javaType用来指定实体类中属性的类型
-
ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
注意点
-
保证sql的可读性,尽量保证通俗易懂
-
注意一对多和多对一中属性名和字段的问题
-
尽量避免慢SQL
面试高频
-
Mysql引擎
-
InnoDB底层
-
索引
-
索引优化
12、动态SQL
什么是动态sql:根据不同调价生成不同的sql语句
动态sql元素和JSTL成基于类似XML的文本处理器相似。在Mybatis之前的版本中,有很多元素需要花时间了解。MyBatis3大大精简了元素种类,现在只需学习原来的一半元素即可,MyBatis采用功能强大的基于OGNL的表达式来淘汰其他大部分元素。 if choose(when,otherwise) trim(where,set) foreach
搭建环境
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
创建一个基础工程
-
导包
-
编写配置文件
-
编写实体类
public class Blog { private String id; private String title; private String author; private Date createTime; private int views; }
-
编写实体类对应的Mapper接口和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.twd.dao.BlogMapper"> </mapper>
IF
<select id="queryBlogIF" parameterType="map" resultType="blog"> select * from blog where 1=1 <if test="title!=null"> and title=#{title} </if> <if test="author!=null"> and author=#{author} </if> </select>
choose(when,other)
<select id="queryBlogChoose" parameterType="map" resultType="blog"> select * from blog <where> <choose> <when test="title!=null"> title=#{title} </when> <when test="author!=null"> author=#{author} </when> <otherwise> views=#{views} </otherwise> </choose> </where> </select>
trim(where,set)
<select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <if test="title!=null"> title=#{title} </if> <if test="author!=null"> author=#{author} </if> </where> </select> <update id="updateBlog" parameterType="map" > update blog <set> <if test="title!=null"> title=#{title}, </if> <if test="anthor!=null"> author=#{author} </if> </set> where id =#{id} </update>
所谓的动态sql,本质还是sql语句,只是我们可以在sql层面,去执行一个逻辑代码
if ,where,set,choose,when...
SQL片段
把重复的sql封装,实现覆用
用sql标签封装,include实现
<sql id="test-queryBlog"> <if test="title!=null"> title=#{title} </if> <if test="author!=null"> author=#{author} </if> </sql> <select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <include refid="test-queryBlog"></include> </where> </select>
注意事项:
-
最好基于单表来定义sql片段
-
里面不要有where标签
Foreach
<select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from blog <where> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id=#{id} </foreach> </where> </select>
动态SQL就是在拼接sql语句,我们只要保证sql的正确性,按照sql的格式,去排列组合就可以了
建议
-
先在mybatis中写好再去拼接
13、缓存
13.1 简介
查询: 连接数据库和资源 一次查询的结果,给他暂存在一个可以直接取到的地方————》内存:缓存 我们再次查询相同的数据,就不需要走数据库,直接走缓存
1.什么是缓存
-
临时数据
-
将用户经常查询的数据放在缓存中,用户去查询数据不从磁盘上查询,而是在缓存上查询,从而提高查询效率,解决高并发系统的性能问题
13.2 MyBatis缓存
-
mybatis包含一个非常强大的查询缓存特性
-
默认定义了两级缓存:一级缓存和二级缓存
-
默认情况下,只有一级缓存开启,(sqlsession级别的缓存,也成为本地缓存)
-
二级缓存需要手动开启和配置,他是基于namespace级别的缓存
-
为了提高扩展性,mybatis定义了缓存接口cache,我们可以通过实现cache接口来自定义二级缓存
-
13.3 一级缓存
一级缓存也叫本地缓存:SqlSession
测试步骤
1.开启日志
2.测试在一个session中查询两次相同的记录
public void queryUserById(){ SqlSession sqlSession = MybatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.queryUserById(1); System.out.println(user); sqlSession.clearCache(); System.out.println("============================"); User user1 = mapper.queryUserById(1); System.out.println(user1); System.out.println(user==user1); sqlSession.close();
sqlSession.clearCache();//清除缓存
13.4 二级缓存
1.开启全局缓存
<!-- 显示的开启全局缓存--> <setting name="cacheEnabled" value="true"/>
查询顺序
二级缓存--->一级缓存--->数据库
缓存就是为了提高查询效率
13.5 自定义缓存(ehcache)
ehcache是一种广泛使用的开源Java分布式缓存,主要面向通用缓存
导包使用
最后Redis做数据库缓存