初识Mybatis

文章目录

      • Mybatis
        • 一.简介
          • 1.1 持久化
          • 1.2 使用持久化服务原因?
        • 二.执行流程
        • 三.搭建环境 (第一个mybatis程序)
        • 四 .CRUD
          • 1.namespace
          • 2.select
          • 3.add
          • 4.update
          • 5.delete
          • 4.2 Map使用
        • 五.xml配置
          • 1.db.properties
          • 2.在核心文件中进行导入
        • 六.类型别名(typeAliases)
        • 七. 映射器(mappers)
          • 方法一:使用resource文件绑定注册
          • 方法二:使用class文件绑定注册
        • 八.ResultMap (结果集映射)
        • 九 .日志工厂
          • 1.标准日志实现
          • 2.Log4j
        • 十.实现分页
          • 1.limit实现分页
          • 2.使用RowBounds分页
          • 3.分页插件PageHelper
        • 十一. 使用注解开发
          • 1.接口中添加注释
          • 2.在mybatis的核心配置文件中注入(使用class 绑定接口)
          • 3.测试
          • Lombok使用
        • 十二. 一对多处理
          • 方法一:按照结果嵌套处理
          • 方法二.按查询嵌套处理
        • 十三. 多对一处理
          • 方法一:按查询嵌套处理
          • 方法二:按查询嵌套处理
          • 小结
          • 注意点:
        • 十四. 动态SQL
          • 1.什么是动态SQL
          • 2.搭建环境
          • if(重点)
            • where
            • set
          • choos、when、otherwise
          • foreach(重点)
        • 十五. 缓存[Cache ](了解即可)
        • 一级缓存(SqlSession级别的缓存)
          • 一级缓存失效情况
        • 二级缓存(namespace级别的缓存)

Mybatis

一.简介

MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github,MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

1.1 持久化
  • JDBC就是一种持久化机制。文件IO也是一种持久化机制。
  • 将数据保存到可永久保存的存储设备中(如磁盘)。
1.2 使用持久化服务原因?

内存断电后数据会丢失。

内存过于昂贵,需要持久化来缓存到外存。

二.执行流程

初识Mybatis_第1张图片

三.搭建环境 (第一个mybatis程序)

==思路:==搭建环境–>导入MyBatis–>编写代码–>测试

3.1 搭建数据库

CREATE DATABASE `mybatis`;

USE `mybatis`;

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
`id` int(20) NOT NULL,
`name` varchar(30) DEFAULT NULL,
`pwd` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `user`(`id`,`name`,`pwd`) values (1,'sun','12345'),(2,'sunshile','12345'),(3,'shile','11231');

3.2 导入依赖包

<dependencies>
    <!--mysql驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.17</version>
    </dependency>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    <!--junit-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

注:Maven静态资源过滤问题 在pom.xml中配置

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
            <include>**/*.properties
            **/*.xml</include>
            </includes>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties
                **/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

3.3 编写mybatis的核心配置文件(resources 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核心配置文件-->
<configuration>
    <!--environments配置环境组-->
    <!--default默认环境-->
    <environments default="development">
        <!--environment单个环境-->
        <environment id="development">
            <!--transactionManager配置事务管理器-->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UFT-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123123"/>
            </dataSource>
        </environment>
    </environments>
    
<!--每一个Mapper.xml都需要在mybatis配置核心文件-->
    <mappers>
        <mapper resource="com/sun/dao/UserMapper.xml"/>
    </mappers>
</configuration>

3.4 编写mybatis工具类(utils)

package com.rui.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;

//sqlSessionFactory—>SessionFactory
public class MyBatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try{
//获取sqlSessionFactory对象
String resource = “mybatis-config.xml”;
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}catch(IOException e) {
e.printStackTrace();
	}
}
     //获取SqlSession连接
   public static SqlSession getSession(){
       return sqlSessionFactory.openSession();
  }

}

3.5 编写Mapper/DAO接口类

import com.kuang.pojo.User;
import java.util.List;

public interface UserMapper {
   List<User> selectUser();
}

3.6 编写实体类pojo

package com.rui.pojo;

public class user {
    private int id;
    private String name;
    private String pwd;

    public user() {
    }

    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;
    }

3.7Dao/mapper接口


//Dao==mapper
public interface UserDao {
    List<User> getuserList();
}

3.8 接口实现类

<?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">
<!--namespace绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.sun.dao.UserDao">
<!--  id对应方法名字  dao-->
    <select id="getuserList" resultType="com.sun.pojo.User">
    select * from mybatis.user;
  </select>
</mapper>

3.9 测试

junit进行测试

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);
        }
    }
}

四 .CRUD

注:增删改需要提交事务。

1.namespace

namespace中的包名要和Dao/mapper接口的包名一致!

2.select

id:对应namespace中的方法名

resultType: sql语句执行的返回值

3.add

编写接口addUser

// 增加一个用户
int addUser(User user);

编写对应的mapper中的sql语句

<insert id="addUser" parameterType="com.sun.pojo.User">
    insert into user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>

测试

@Test
public void addUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    int ser = mapper.addUser(new User(6, "wangwu", "112321"));
    if(ser>0){
        System.out.println("插入成功!");
    }
    //提交事务
    sqlSession.commit();
    //关闭事务
    sqlSession.close();;
}
4.update
5.delete

思路:

1.编写接口

  1. 编写对应的mapper中的sql语句
  2. 测试
4.2 Map使用

当表单的数据字段过多时,删除修改字段时,过程较麻烦,使用Map可以简化过程!

1.编写接口

//使用map
int addUser2(Map<String, Object> map);
  1. 编写对应的mapper中的sql语句

       <insert id="addUser" parameterType="map">
        insert into mybatis.user (id, name) values (#{id}, #{name});
    </insert>
    
  2. 测试

@Test
public void addUser(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    HashMap<String, Object> map = new HashMap<String, Object>();
    map.put("id",7);
    map.put("name","hello");
    mapper.addUser2(map);

    sqlSession.commit();
    sqlSession.close();
}

Map传递参数,直接在sql中取出key即可!【parameterType=“map”】

对象传递参数,直接在sql中取对象的属性即可!【parameterType=“Object”】

只有一个基本类型参数的情况下,可以直接在sql中取到!

五.xml配置

configuration(配置文件)
properties(属性文件)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

编写一个配置文件

初识Mybatis_第2张图片

1.db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username=root
password=942626
2.在核心文件中进行导入

初识Mybatis_第3张图片



<configuration>

    <properties resource="db.properties"/>

    <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 resource="com/sun/dao/UserMapper.xml"/>
    mappers>

configuration>

六.类型别名(typeAliases)

  1. 类型别名可为 Java 类型设置一个缩写名字。

2.它仅用于 XML 配置,意在降低冗余的全限定类名书写.


    <typeAliases>
        <typeAlias type="com.sun.pojo.User" alias="User"/>
    typeAliases>

3.可以指定一个包名,MyBatis 会在包名下面搜索需要的 JavaBean,比如:

<typeAliases>
  <package name="com.sun.pojo"/>
typeAliases>

应用场景:

1.如果实体类多,第二种方法更合适

2.如果实体类少,可以用第一种,第二种则 不行, 如果非要改,需要在实体上增加注释

@Alias("user")
public class User {

七. 映射器(mappers)

MapperRegistry:注册绑定mapper文件

方法一:使用resource文件绑定注册
<mappers>
    <mapper resource="com/sun/dao/UserMapper.xml"/>
mappers>
方法二:使用class文件绑定注册
<mappers>
  <mapper class="com.sun.dao.UserMapper.xml"/>
mappers>

使用class注意:

1.接口和它的Mapper配置文件必须同名

2.接口和它的Mapper配置文件必须在同一个包下

一般使用resource文件绑定注册更好

八.ResultMap (结果集映射)

功能:

当数据中的字段和实体类中的字段不一致时,可以用ResultMap 解决

初识Mybatis_第4张图片

初识Mybatis_第5张图片

resultMap 元素是 MyBatis 中最重要最强大的元素。

ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。

结果集映射

id name pwd
id name password

    <resultMap id="userMap" type="user">

        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="=pwd" property="password"/>
    resultMap>
  <select id="getuserList" resultMap="userMap">
    select * from user
  select>

九 .日志工厂

Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:

  • SLF4J

  • Apache Commons Logging

  • Log4j 2

  • Log4j

  • JDK logging

    具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。如果一个都未找到,日志功能就会被禁用。

1.标准日志实现

​ 指定 MyBatis 应该使用哪个日志记录实现。如果此设置不存在,则会自动发现日志记录实现


   

测试,可以看到控制台有大量的输出!我们可以通过这些输出来判断程序到底哪里出了Bug

2.Log4j

简介:

  • Log4j是Apache的一个开源项目
  • 通过使用Log4j,我们可以控制日志信息输送的目的地:控制台,文本,GUI组件…
  • 我们也可以控制每一条日志的输出格式;
  • 通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

1.导入log4的包

<dependency>
   <groupId>log4jgroupId>
   <artifactId>log4jartifactId>
   <version>1.2.17version>
dependency>

2、配置文件编写

#将等级为DEBUG的日志信息输出到console和file这两个目的地,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、设置setting日志实现

<settings>
   <setting name="logImpl" value="LOG4J"/>
settings>

4、使用Log4j进行输出!

**注意导包:org.apache.log4j.Logger **

MyTest表示对该类的测试
static Logger logger = Logger.getLogger(UseMapperTest.class);

@Test
public void selectUser() {
   logger.info("info:进入info方法");
   logger.debug("debug:进入debug方法");
   logger.error("error: 进入error方法");
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);
   List<User> users = mapper.selectUser();
   for (User user: users){
       System.out.println(user);
  }
   session.close();
}

使用Log4j 输出日志

十.实现分页

在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使用分页进行查询,也就是每次处理小部分数据,这样对数据库压力就在可控范围内。

1.limit实现分页

1.1语法

SELECT * FROM table LIMIT stratIndex,pageSize

1.2接口(mapper)

List<User> selectUser(Map<String,Integer> map);

1.3 接口实现

  <select id="getUserByLimit" parameterType="map" resultMap="userMap">
    select * from user limit #{startIndex},#{pagesize}
    </select>

1.4 测试

@Test
    public void getUserByLimit(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        map.put("startIndex",0);
        map.put("pagesize",4);
        List<User> userList = mapper.getUserByLimit(map);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();

    }
2.使用RowBounds分页

区别:不使用SQL实现分页

2.1 接口

List<User> getUserByRowBounds();

2.2 接口实现

<select id="getUserByRowBounds" resultMap="userMap">
    select *from user
</select>

2.3 测试

@Test
    public void getUserByRowBounds(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
	//RowBound实现
	RowBounds rowBounds = new owBounds(1,4);
        List<User> userList = sqlSession.selectList("com.sun.dao.getUserByRowBounds",null,rowBounds);
        for (User user : userList) {
            System.out.println(user);
        }
        sqlSession.close();

    }
3.分页插件PageHelper

分页插件支持任何复杂的单表、多表分页。
初识Mybatis_第6张图片

网址:https://pagehelper.github.io/

十一. 使用注解开发

1.增删改查,关联映射,动态SQL语言等知识,其所有的配置是通过XML完成的,但是注释配置不需要xml配置。

2.mybatis提供了@Insert、 @Delete、@Update、@Select等常用注解。

**注意:**利用注解开发就不需要mapper.xml映射文件了

需要建立的包如下:
初识Mybatis_第7张图片

1.接口中添加注释
@Select("select * from user")
//查询全部用户
public List<User> getAllUser();
2.在mybatis的核心配置文件中注入(使用class 绑定接口)

<mappers>
    <mapper class="com.sun.dao.UserMapper"/>
mappers>
3.测试

本质:反射机制

底层:动态代理

@Test
public void testGetAllUser() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    List<User> users = mapper.getAllUser();
    for (User user : users){
        System.out.println(user);
    }
    sqlSession.close();
}
Lombok使用

Lombok项目是一个Java库,它提供了一组有用的注释,用来消除Java类中的大量代码。

使用步骤:

  1. 在IDEA中安装Lombok插件

  2. 在项目中导入lombok的jar包

    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <version>1.18.10version>
        <scope>providedscope>
    dependency>
    

使用实现案例

初识Mybatis_第8张图片

十二. 一对多处理

一个老师对应多个学生

1.搭建环境,编写实体类

@Data
public class Student {
   private int id;
   private String name;
   private int tid;
}
@Data
public class Teacher {
   private int id;
   private String name;
   //老师对应学生
   private List<Student> students;
}

处理数据库数据

方法一:按照结果嵌套处理

1.TeacherMapper接口编写方法

public Teacher getTeacher(int id);//获取指定老师,及老师下的所有学生

2.编写对应mapper接口

<mapper namespace="com.sun.dao.TeacherMapper">
   <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=#{id}
   select>

   <resultMap id="TeacherStudent" type="Teacher">
       <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>
mapper>

3.绑定接口(mybatis-config.xml)

<mappers>
    <mapper resource="com/sun/dao/TeacherMapper.xml"/>
    <mapper class="com.sun.dao.StudentMapper"/>
mappers>

4.测试

@Test
public void testTeacher(){
   SqlSession session = MybatisUtils.getSession();
   TeacherMapper mapper = session.getMapper(TeacherMapper.class);
   Teacher teacher = mapper.getTeacher(1);
   System.out.println(teacher);
   }
方法二.按查询嵌套处理

1、TeacherMapper接口编写方法

//获取指定老师,及老师下的所有学生
public Teacher getTeacher1(int id);
2,编写mapper对应的配置文件
<select id="getTeacher1" resultMap="TeacherStudent1">
select * from teacher where id = #{id}
select>
<resultMap id="TeacherStudent1" type="Teacher">

   <collection property="students" javaType="ArrayList" ofType="Student" column="id" select="getStudentByTeacherId"/>
resultMap>
<select id="getStudentByTeacherId" resultType="Student">
  select * from student where tid = #{id}
select>

3.映射文件编写(MyBatis-config.xml)

4.测试

@Test
public void testGetTeacher2(){
   SqlSession session = MybatisUtils.getSession();
   TeacherMapper mapper = session.getMapper(TeacherMapper.class);
   Teacher teacher = mapper.getTeacher1(1);
   System.out.println(teacher);   
}

十三. 多对一处理

多个学生对应一个老师

1.数据库设计

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');

2.引入依赖(maven)


<dependency>
 <groupId>org.projectlombokgroupId>
 <artifactId>lombokartifactId>
 <version>1.16.10version>
dependency>

3,编写实体类

@Data 
public class Teacher {
   private int id;
   private String name;
}
@Data
public class Student {
   private int id;
   private String name;
   //多个学生可以是同一个老师,即多对一
   private Teacher teacher;
}

4.编写接口

public interface StudentMapper {
}
public interface TeacherMapper {
}

5.接口映射



<mapper namespace="com.sun.dao.StudentMapper">

mapper>


<mapper namespace="com.sun.dao.TeacherMapper">

mapper>

处理数据库数据

方法一:按查询嵌套处理

1.添加接口方法(给StudentMapper接口增加方法)

public List<Student> getStudents();//学生对老师  多对一

2.编写对应的mapper.xml文件



<mapper namespace="com.sun.dao.StudentMapper">
   <select id="getStudents" resultMap="StudentTeacher">
    select * from student
   select>
    
   <resultMap id="StudentTeacher" type="Student">

       <association property="teacher"  column="tid" javaType="Teacher" select="getTeacher"/>
   resultMap>

    <select id="getTeacher" resultType="teacher">
      select * from teacher where id = #{id}
   select>

mapper>

3.绑定接口(mybatis-config.xml)


<mappers>
    <mapper resource="com/sun/dao/TeacherMapper.xml"/>
    <mapper class="com.sun.dao.StudentMapper"/>
mappers>

4.测试

@Test
public void testGetStudents(){
   SqlSession session = MybatisUtils.getSession();
   StudentMapper mapper = session.getMapper(StudentMapper.class);

   List<Student> studentList = mapper.getStudents();

   for (Student student : studentList){
       System.out.println(
               "学生名:"+ student.getName()
                       +"\t老师:"+student.getTeacher().getName());
  }
}
方法二:按查询嵌套处理

1.添加接口方法(给StudentMapper接口增加方法)

2.编写对应的mapper文件(与方法一的mapper不同,其他相同)

<select id="getStudents" resultMap="StudentTeacher" >
  select s.id sid, s.name sname , t.name tname
  from student s,teacher t
  where s.tid = t.id
select>

<resultMap id="StudentTeacher" type="Student">
   <id property="id" column="sid"/>
   <result property="name" column="sname"/>
   <association property="teacher" javaType="Teacher">
       <result property="name" column="tname"/>
   association>
resultMap>

3.绑定接口(mybatis-config.xml)

4.测试

小结
  1. 关联 - association 【多对一】
  2. 集合 - collection 【一对多】
  3. javaType & ofType
    1. JavaType用来指定实体类中的类型
    2. ofType用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
注意点:
  • 保证SQL的可读性,尽量保证通俗易懂
  • 注意一对多和多对一,属性名和字段的问题
  • 如果问题不好排查错误,可以使用日志,建议使用Log4j

十四. 动态SQL

1.什么是动态SQL

==什么是动态SQL:==动态 SQL 是 MyBatis 的强大特性之一,可以根据不同的条件生成不同的SQL语句

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach
2.搭建环境

新建一个数据库

数据库字段:

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

1.创建一个Mybatis工程

2.创建一个工具类(使用UUID自动生成随机数)

public class IDUtil {

   public static String genId(){
       return UUID.randomUUID().toString().replaceAll("-","");
  }
}

3.编写实体类

@Data
public class Blog {
    private String id;
    private String title;
    private String author;

    private Date createTime;
    private int views;
}

4.编写一个实体类接口(Mapper接口及xml文件)

public interface BlogMapper {
}


<mapper namespace="com.sun.dao.BlogMapper">

mapper>

5.编写mybatis核心配置文件

 <mapper resource="com/sun/dao/BlogMapper.xml"/>
</mappers>

6.插入初始化数据

6.1 编写接口

int addBlog(Blog blog);

6.2 sql配置文件


  insert into blog (id, title, author, create_time, views)
  values (#{id},#{title},#{author},#{createTime},#{views});

6.3 初始化接口配置

@Test
public void addInitBlog(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   Blog blog = new Blog();
   blog.setId(IDUtil.genId());
   blog.setTitle("Mybatis如此简单");
   blog.setAuthor("狂神说");
   blog.setCreateTime(new Date());
   blog.setViews(9999);

   mapper.addBlog(blog);

   blog.setId(IDUtil.genId());
   blog.setTitle("Java如此简单");
   mapper.addBlog(blog);

   blog.setId(IDUtil.genId());
   blog.setTitle("Spring如此简单");
   mapper.addBlog(blog);

   blog.setId(IDUtil.genId());
   blog.setTitle("微服务如此简单");
   mapper.addBlog(blog);

   session.close();
}
if(重点)

​ 元素是简单的条件判断,可以用来实现某些简单的条件选择。

1.1 编写接口类

List<Blog> queryBlogIf(Map map);

1.2编写SQL语句


1.3 测试

@Test
public void testQueryBlog(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap map = new HashMap();
   map.put("title","Mybatis如此简单");
   map.put("author","狂神说");
   List blogs = mapper.queryBlogIf(map);

   System.out.println(blogs);
   session.close();
}
where

​ 当if元素较多时,可能会拼接成where and或者 where or之类的关键字多余的错误SQL语句,使用元素可以解决这类问题,只有元素的条件成立时,才会拼接SQL语句时加上where关键字。如果出现where and或者where or时, 元素会自动剔除where关键字后面多余的and或or.

where语句使用


set

​ 和元素可以组装update语句,只有当《set》元素的条件都成立的时候,才会组装SQL语句时加上set关键字,元素包含子元素,每个元素包含SQL语句后面会有一个逗号,拼接好的SQL语句中会包含多余的逗号,从而造成SQL语法错误,但是元素能将SQL语句中多余的逗号剔除。

1.1 编写接口类

int updateBlog(Map map);

1.2编写SQL语句

<update id="updateBlog" parameterType="map">
  update blog
     <set>
         <if test="title != null">
            title = #{title},
         </if>
         <if test="author != null">
            author = #{author}
         </if>
     </set>
  where id = #{id};
</update>

1.3 测试

@Test
public void testUpdateBlog(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap<String, String> map = new HashMap<String, String>();
   map.put("title","hello");
   map.put("author","hi");
   map.put("id","110");
   mapper.updateBlog(map);
   session.close();
}
choos、when、otherwise

​ choose元素的用法和case元素用法类似,可以从多个选项中选择一个,可以使用mybatis提供的、和元素来实现,元素可以判断元素的条件是否成立,如果有一个成立,则不在判断后面的元素的条件是否成立,元素执行结束,如果条件都不满足,则执行元素中的SQL语句。

sql文件的编写


foreach(重点)

​ 元素主要是迭代一个集合,在SQL语句中通常在in这个关键字的后面。

提示: 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

字段属性解析:

   collection:指定输入对象中的集合属性
   item:每次遍历生成的对象
   index:指定一个变量名称,表示每次迭代到的位置
   open:开始遍历时的拼接字符串
   close:结束时拼接的字符串
   separator:遍历对象之间需要拼接的字符串

collection属性需要根据具体情况进行设定,通常分为两种情况:

1.如果向SQL语句传递的是单参数且参数类型为List< E >,collection属性值为list

2.如果向SQL语句传递的是单参数且参数类型为array数组,collection属性值为array.

操作数据

1.编写接口

List<Blog> queryBlog(Map map);

2.编写sql


3.测试

@Test
public void testQueryBlog(){
   SqlSession session = MybatisUtils.getSession();
   BlogMapper mapper = session.getMapper(BlogMapper.class);

   HashMap 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);
   System.out.println(blogs);
   session.close();

十五. 缓存[Cache ](了解即可)

缓存定义:存在内存中的临时数据

​ 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题.

Mybatis缓存分为一级缓存和二级缓存。

  • 默认情况下,只有一级缓存开启。(也称为本地缓存)
  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
  • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

一级缓存(SqlSession级别的缓存)

​ 一级缓存是SQLsession级别的缓存,当同一个SQLsession中执行两次相同的SQL语句时,会将第一次的数据存入到一级缓存中,第二次查询时就会从缓存中读取数据,从而提高查询性能。 但是当SQLSesseion执行insert,delete、和update操作,并提交到数据库中,或者SQLsession结束后,这个SQLSession中的一级缓存就不存在了。

测试实现:

1.加载日志

2.编写接口

User queryUserById(@Param("id") int id);

3.编写对应的xml文件


4.测试

@Test
public void testQueryUserById(){
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);

   User user = mapper.queryUserById(1);
   System.out.println(user);
   User user2 = mapper.queryUserById(1);
   System.out.println(user2);
   session.close();
}

结果分析:

当执行第二次相同查询时,由于第一次进行数据库访问,第二次访问时,直接从缓存中读取数据,从而提高查询性能。

一级缓存失效情况

1.SqlSesssion不同

2.sqlSession相同,查询条件不同

3.增删改改变了原来的数据

4.缓存的清理(手动清理)

@Test
public void testUser(){
   SqlSession session = MybatisUtils.getSession();
   UserMapper mapper = session.getMapper(UserMapper.class);

   User user = mapper.queryUserById(1);
   System.out.println(user);

   session.clearCache();//手动清除缓存

   User user2 = mapper.queryUserById(1);
   System.out.println(user2);

   System.out.println(user==user2);

   session.close();
}

二级缓存(namespace级别的缓存)

​ mybatis的二级缓存是namespace级别的缓存,多个SQLsession公用二级缓存,他们使用同一个Mapper语句操作数据库获得的数据就会存在二级缓存中。

测试数据

1.开启全局缓存(mybatis-config.xml)

<setting name="cacheEnabled" value="true"/>

2.在Mapper.xml中使用缓存



//可以存储结果对象或列表的 512 个引用

3.测试

4.结论

  • 只要开启了二级缓存,在同一个Mapper中的查询时,可以在二级缓存中拿到对应数据
  • 查出的数据都会被默认先放在一级缓存中
  • 只有当前会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

5.缓存原理

img

总结:

视频来自:狂神说 mybatis https://www.bilibili.com/read/cv5702420

资料参考:https://www.cnblogs.com/renxuw/p/13047424.html

你可能感兴趣的:(mybatis)