Mybatis框架的使用

1什么是框架?

​ 他是我们软件开发的一套解决方案,不同的框架解决的是不同的问题。
​ 使用框架的好处:框架封装了很多细节,使开发者可以使用极简的方式实现功能,提高开发效率

1.1三层架构

​ 表现层:Spring MVC
​ 用于展示数据
​ 业务层:
​ 处理业务需求
​ 持久层:Mybatis
​ 与数据库交互

1.2持久层技术解决方案

​ JDBC技术:
​ Conncetion
​ PreparedStatment
​ ResultSet
​ Spring的Jdbctemplate
​ Spring中对jdbc的简单封装
​ Apache的DBUtils
​ 也是对jdbc的简单封装

​ 传统JDBC的连接数据库 获取预处理对象 执行语句 返回结果集代码 有大量重复 效率不高 并且还要学习sql语句
​ 为了解决这些问题 就出现了这个框架

4Mybatis概述 mybatis是一颗持久层框架 使用java编写
它封装了很多jdbc操作的很多细节 ,使开发者只需要关注sql语句 无需关注 注册驱动 创建连接 等复杂过程
它使用了ORM思想实现了结果集的封装
ORM:
对象关系映射
就是把数据库表的列明和类的属性对应起来 表名和类名对应
让我们通过操作实体类而操作数据库表

2 搭建Mybatis环境

2.1新建项目

​ 1,新建一个普通的maven项目

​ 2.删除src目录

​ 3.导入maven依赖

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--父工程-->
    <groupId>org.example</groupId>
    <artifactId>Myproject</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>Mybatis</module>
    </modules>

    <!--导入依赖 -->
    <dependencies>
        <!--mysql驱动 -->

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</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>
<!--单元测试的时候该文件夹下的文件可以导出-->
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

</project>

2.2 创建一个模块

2.2.1编写mybaties工具类

package 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 {
            //官网拿下来的    死的语句
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        //有了SqlSessionFactory 我们就鞥获得sqlsession实例 这个实例包含了执行sql的所有方法
    }
    public static SqlSession getSqlSession(){

            return sqlSessionFactory.openSession(); //相当于得到了connection对象

    }
}

2.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.jdbc.Driver" />
                     <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8" />
                     <property name="username" value="root" />
                     <property name="password" value="123456" />
                 </dataSource>
             </environment>
         </environments>

    <mappers>
        <mapper resource="dao/UserMapper.xml"/>
    </mappers>
     </configuration>

2.3 编写代码

实体类

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

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }
}

Dao接口

package dao;

import pojo.User;

import java.util.List;

/*
操作数据库对象实体
 */
public interface UserDao {
    List<User> getUserList();
}

接口实现类以前是实现类 现在是xml文件

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybayis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace 绑定一个Dao/Mapper接口 相当于实现该接口-->
<mapper namespace="dao.UserDao">
    <!--select标签 代表内容是查询 id对应接口中要实现的方法-->
    <!--resultType标签 代表返回类型 要写全路径-->
    <select id="getUserList" resultType="pojo.User">
        select * from user
    </select>

</mapper>

2.4测试

测试代码

package dao;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import pojo.User;
import utils.MybatisUtils;

import java.util.List;

public class UserDaoTest {
    @Test
   public void test(){
        //第一步 获得sqlsession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //第二步 为了调用sql语句 所以我们需要类的对象
        //因为 mapper.xml实现了改接口 又因为针对接口编程
        //所以我们获取的是接口的类 内部会自动使用实现类的方法
        UserDao mapper = sqlSession.getMapper(UserDao.class);//实际返回的是xml对象
        //第三步执行sql并遍 历
        List<User> list = mapper.getUserList();
        for(User user:list){
            System.out.println(user);
        }
        //关闭
        sqlSession.close();
    }
}

报错1

org.apache.ibatis.binding.BindingException: Type interface dao.UserDao is not known to the MapperRegistry.

每一个mapper.xml(就是接口的实现文件) 都需要在Mybatis核心配置中注册 否则报错

报错2

初始化失败问题找不到mapper.xml配置文件

虽然我们有这个文件但是运行时没有加载到target目录中 手动配置资源过滤即可

报错3

报错:某行某列无法解析 等等 都是因为核心配置文件内容有错 注释不可以写中文

总结

SqlSession代表和数据库的一次会话 用完关闭

Sqlsession和Connection一样都是非线程安全的

非线程安全 不能把这个变量定义在方法外 A用完关了 B就用不了了 每次使用都应该获取新的对象

mapper接口没有实现类 ,但是 mybatis会为这个接口生成一个代理对象

​ UserDao mapper = sqlSession.getMapper(UserDao.class)(接口和xml必须绑定)

俩个重要的配置文件

​ 全局配置文件 :包含数据库连接 信息事务管理等信息 系统运行环境信息

​ 接口的配置文件 保存了每一个sql语句映射信息

​ 将sql抽取出来

3增删改查(查询的例子)

0单个参数与多个参数

单个参数mybatis不会做特殊处理

​ #{参数名}:取出参数值 下面的id随意些 因为只有一个参数且为基本类型 也就无所谓了

delete from tb1_employee where id =#{asdasfsa} 

多个参数值 会做特殊处理

​ 多个参数会被封装为一个map

​ key:param1.。。。。paramN

​ value :为传入的值

​ 如果参数写了#{id} 是取不到的 因为没有这个key

正确写法这样 但是很麻烦 全是param 不好看

select * from tb1_employee where id =#{param1} and last_name=#{param2}

解决:封装参数时@param(“key”)

public Employee getEmployeemore(@Param("id") Integer id, @Param("lastName")String lastName);

如果不写注解 可以通过传map的方式

总结

第一个场景:public Employee getEmployee (@param(“id”) int id, String name)

取值 id====>#{id/param1} name=#{param2}

第二个场景:public Employee getEmployee (int id, Employee emp)

取值 id====>#{param1} name=#{param2.name}

第二个场景:public Employee getEmployee (List ids)

取值 id====>#{list[0]} 而不是ids【0】 set 数组同理

需求

​ 1如果返回值是一个list 怎么写

​ 配置文件中 resultType=list中存储的类型

​ 2 如果返回值是一个map

​ resultType写map

​ 3如果返回一个map 而且key是id 或者name 如何制定

​ 在类上写注解 @MapKey(“字段名”)

# $的区别

#{} 以预编译的形式 相当preparedstatement 防止sql注入

${} 取出的值直接赋值 一般不支持占位符的用这个 比如将表名作为参数传递就用这个

源码解析参数

上面的参数 mybatis如何实现 下面查看源码

​ 1首先获取 参数 名并封装 names:{0=id ,1=name}

​ 2获取每个标了@param的注解值

​ 3每次解析一个参数给map中保存

​ key :如果标了注解 就是注解的值

​ 如果没表注解 值就是索引值

4如果只有一个元素 并且没有注解 直接返回args[0]

5如果有多个参数

详细说一下接口的配置文件

namespace:要实现的接口

id:接口中的方法

resultType 返回值类型

parameterType 参数类型

1编写接口

List<User> getById(int id);

2编写实现类

<select id="getById" resultType="pojo.User" parameterType="int">
        select * from user where id = #{id}
    </select>

3测试

public void Test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao user  =  sqlSession.getMapper(UserDao.class);
        List<User> user1=  user.getById(1 );
        for (User user2 : user1) {
            System.out.println(user2);
        }
    }

注意点 增删改查需要提交事务

4错误分析

1xml文件中写中文乱码

2标签写错 insert标签写成select标签

3资源文件路径用/ 导入类用点

4配置文件不能出错 报错内容从下网上看

5 增删改不起作用 因为没有提交事务

5模糊查询的俩种方式

第一种

<select id="getByLike" resultType="pojo.User">
        select * from user where name like #{name}
    </select>
List<User> users=  user.getByLike("%a%");

第二种有sql注入的危险

<select id="getByLike" resultType="pojo.User">
        select * from user where name like "%" #{name}"%"
    </select>
List<User> users=  user.getByLike("a");

4配置解析

1核心配置文件

environment必须有

transactionManager :事务管理器

​ dataSource

可以快速切换环境

Mybatis配置文件包含了深深影响mybatis行为的设置和属性

Mybatis默认事务管理器是JDBC 连接池是POOLED

2属性之properties优化

我们可以通过properties来实现引用配置文件

在xml文件中 有些属性有顺序 properties被规定必须写在最前面

编写一个properties配置文件

db.properties

driver=com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

在核心配置文件中引入

<?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配置文件-->
        <properties resource="properties-config.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="dao/UserMapper.xml"/>
        </mappers>
     </configuration>

以上我们将连接数据库的所有参数转移到另外的文件 在引入 完成了优化

3配置之别名优化typeAliases

必须写在第三个位置 第二个位置是setting

类型别名是为java类型设置的一个短的名字

存在的意义仅在于减少类的完全限定名冗余 别名不区分大小写

方式1

<!--给实体类起别名-->
<typeAliases>   
        <typeAlias type="pojo.User" alias="User"></typeAlias>
</typeAliases>

接口的配置文件中修改

<!--上面制定了路径的别名叫User 所以下面写User-->
<select id="getById" resultType="User">    
        select * from user where id = #{id}</select>
</select>

方式2 批量起别名 指定包名即可

<typeAliases>
         <package name="pojo"/>
</typeAliases>

接口的配置文件中修改

<!--上面已经锁定了包 会自动检索包下面的类 所以直接写类名 但是建议小写-->
<select id="getUserList" resultType="User">  
        select * from user
</select>

在实体类别少的时候用第一中

如果实体类比较多 用第二种

第一种可以自己定义别名 第二种不行如果有注解则别名为注解值

@Alias(“别名”)直接写到类上 给类起别名

4setting驼峰命名

开启驼峰命名

<settings> 
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

5映射器mappers

mapperRegistry:绑定注册mapper文件

<mappers>
            <mapper resource="dao/UserMapper.xml"/>
</mappers>

​ resource:引用类路径下的sql映射文件

​ url:引用网络路径或者磁盘路径下的sql映射文件

​ class :引用(注册) 此标签下的xml必须与对应的接口在一个包下且同名

6生命周期和作用域

​ 错误的使用会出现严重的并发问题

sqlsessionfactory:

​ 一旦创建了sqlsessionfactory就被丢弃了 所以是局部变量

sqlsessionfactory:

​ 可以理解为数据库连接池

​ sqlsessionfactory一旦被创建就会一直运行没有任何理由丢弃或创建一个新的

​ 作用域为整个应用期间

sqlsession

​ 每个线程都有各自的sqlsession

​ 用完赶紧关闭

5实体类字段和数据库字段不一致

解决方法:resultMap标签

<!--增加resultMap属性 id是名字 type是返回值类型-->
<resultMap id="userMap" type="User">
    <!--colum是数据库的字段 property是对象的字段 这里让他们对应上-->
	<result column="pwd" property="password"/>
</resultMap>
<!--对象用:assocation   集合用collection 替换result-->
<!--这里=号是上面resultMap的id-->
<select id="getById" resultMap="userMap">
	select * from user where id = #{id}
</select>

6日志

1日志工厂

STDOUT_LOGGING

打错一个字符都不行

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

2Log4j

1先导入log4j包

<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

2配置信息

resource文件下创建properties文件并写入配置信息

log4j.rootLogger = debug,A,B,C
# 输出到控制台
log4j.appender.A = org.apache.log4j.ConsoleAppender
log4j.appender.A.Target = System.out
log4j.appender.A.layout = org.apache.log4j.PatternLayout
log4j.appender.A.layout.ConversionPattern = %p %t %c - %m%n
# 输出到日志文件
log4j.appender.B = org.apache.log4j.DailyRollingFileAppender
log4j.appender.B.File = logs/log.log
log4j.appender.B.Append = true
log4j.appender.B.Threshold = DEBUG # 输出EBUG级别以上的日志
log4j.appender.B.layout = org.apache.log4j.PatternLayout
log4j.appender.B.layout.ConversionPattern = %p %t %c - %m%n
# 保存异常信息到单独文件
log4j.appender.C = org.apache.log4j.DailyRollingFileAppender
log4j.appender.C.File = logs/error.log # 异常日志文件名
log4j.appender.C.Append = true
log4j.appender.C.Threshold = ERROR #只输出ERROR级别以上的日志
log4j.appender.C.layout = org.apache.log4j.PatternLayout
log4j.appender.C.layout.ConversionPattern = %p %t %c - %m%n

3mybatis核心配置文件中写入

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

4简单使用

​ 1导包

​ import org.apache.log4j.Logger;

​ 2测试

static Logger logger = Logger.getLogger(UserDaoTest.class);

7分页

7.1limit实现分页

 <select id="getById" resultMap="userMap" resultType="User" parameterType="map">
        select * from user limit #{start},#{end}
    </select>
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        Map map = new HashMap<String,Integer>();
        map.put("start",0);
        map.put("end",2);
        List<User> list = mapper.getById(map);
        for (User user : list) {
            System.out.println(user);
        }
        //关闭
        sqlSession.close();

8注解开发

1注解在接口上 2在核心配置文件添加mapper 3测试

public interface UserDao {
    @Select("select * from user")
    public List<User> getUser();
}
<mappers>
	<mapper class="dao.UserDao"/>
</mappers>
ublic class UserDaoTest {
    @Test
   public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        List<User> users = mapper.getUser();
        for (User user : users) {
            System.out.println(user);
        }


        //关闭
        sqlSession.close();
    }

}

当有多个参数的时候

public interface UserDao {
    @Select("select * from user where id =#{id} and username = #{username}")
    public List<User> getUser(@Param("id") int id,@param("username") String username);
}

如果参数是引用类型就不用写

public interface UserDao {
    @Select("insert into user values(#{id},#{name},#{pwd})")
    public List<User> getUser(User user);
}

9多对一的处理

方式1

Student类

package pojo;

public class Student {
    private int id;
    private String name;

    private Teacher teacher;

    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 Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }



    public Student(int id, String name,Teacher teacher) {
        this.id = id;
        this.name = name;
        this.teacher=teacher;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", teacher=" + teacher +
                '}';
    }

    public Student() {
    }
}

老师类

package pojo;

public class Teacher {
    private int id;
    private String name;


    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 Teacher() {
    }

    public Teacher(int id, String name) {
        this.id = id;
        this.name = name;

    }

    @Override
    public String toString() {
        return "teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

StudentMapper,xml配置文件

<mapper namespace="dao.StudentMapper">
    <select id="getStudent" resultMap="aaa">
        select * from student
    </select>
    <resultMap id="aaa" type="Student">
        <result property="id" column="id" />
        <result property="name" column="name"/>
        <association property="teacher" column="teacherid" javaType="Teacher" select="getTeacher"/>
    </resultMap>

    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id =#{teacherid}
    </select>
</mapper>

方式2

<select id="getStudent2" resultMap="bbb">
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.teacherid=t.id;
    </select>

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

执行结果:

Student{id=1, name=‘saa’, teacher=teacher{id=1, name=‘asa’}}
Student{id=2, name=‘assss’, teacher=teacher{id=1, name=‘asa’}}

10一对多处理

方式1

Student类

package pojo;

public class Student {
    private int id;
    private String name;
    private int teacherid;

    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 int getTeacher() {
        return teacherid;
    }

    public void setTeacher(int teacherid) {
        this.teacherid = teacherid;
    }



    public Student(int id, String name,int teacherid) {
        this.id = id;
        this.name = name;
        this.teacherid=teacherid;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", teacherid=" + teacherid +
                '}';
    }

    public Student() {
    }
}

Teacher类

package pojo;

import java.util.List;

public class Teacher {
    private int id;
    private String name;
    List<Student> studentList;

    public Teacher() {}

    public Teacher(int id, String name, List<Student> studentList) {
        this.id = id;
        this.name = name;
        this.studentList = studentList;
    }

    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 List<Student> getStudentList() {
        return studentList;
    }

    public void setStudentList(List<Student> studentList) {
        this.studentList = studentList;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", studentList=" + studentList +
                '}';
    }
}

package dao;

import org.apache.ibatis.annotations.Select;
import pojo.Teacher;

import java.util.List;

public interface TeacherMapper {
    public List<Teacher> getTeacher(int id);
}


<?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="dao.TeacherMapper">
    <select id="getTeacher" resultMap="aaa">
        select * from teacher where id = #{tid}
    </select>

    <resultMap id="aaa" type="Teacher">
        <collection property="studentList" column="id" javaType="ArrayList" ofType="Student"  select="getStudent"/>
    </resultMap>

    <select id="getStudent" resultType="Student">
        select * from student where teacherid=#{id}
    </select>
</mapper>

方式2

<?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="dao.TeacherMapper">
   <select id="getTeacher" resultMap="TeacherStudent">
       select s.id sid,s.name sname ,t.id tid,t.name tname
       from student s,teacher t
       where s.teacherid=t.id and t.id=#{id}
   </select>
    <resultMap id="TeacherStudent" type="Teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="studentList" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="teacherid" column="teacherid"/>
        </collection>
    </resultMap>

</mapper>

11动态sql

​ 什么是动态sql:根据不同的条件生成不同的sql语句

1if语句

接口mapper

package dao;

import pojo.Blog;

import java.util.List;
import java.util.Map;

public interface BlogMapper {
   public List<Blog> queryByMap(Map map);
}

mapperxml

<?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="dao.BlogMapper">

    <insert id="addBook" parameterType="Blog">
        insert into blog values(#{id},#{title},#{author},#{createTime},#{views})
    </insert>

    <select id="queryByMap" parameterType="map" resultType="Blog">
        select * from blog where 1=1 <!--1=1相当于 不带查询条件 全部查出来 不正规 用where改进-->
        <if test="author!=null"><!--如果map中有author字段 就拼接下面的语句-->
            and author = #{author}
        </if>
        <if test="title!=null">
            and title=#{title}
        </if>
    </select>

</mapper>

上面的有问题

​ 如果只查询一个条件就变成了 select * from blog where and author = #{author} where后面直接就是and

这样会报错 要是能自动去掉and就好了

2where

把上述的if语句都放到where标签 如果是第一个就自动去掉and 如果不是就不去掉and 如果没有where条件就全部查询

<select id="queryByMap" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <if test="author!=null">
                and author = #{author}
            </if>
            <if test="title!=null">
                and title=#{title}
            </if>
        </where>
    </select>

3Choose(when otherwise)

这个条件只会执行第一次读取到的条件 后面的when不会执行 如果when中的都没有合适的条件就执行other的

<select id="queryByMap" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <choose>
                <when test="title!=null">
                    and title=#{title}
                </when>
                <when test="views!=null">
                    and views=#{views}
                </when>
                <otherwise>
                   and id=1
                </otherwise>
            </choose>
        </where>
    </select>

4set

会根据情况自动去掉逗号

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

5SQL片段

在增删该查过程中有非常多的if语句 我们能将这些重复的提取出来 用的时候引入即可

<mapper namespace="dao.BlogMapper">
    <sql id="ifstatment">
        <if test="title!=null">
            title=#{title},
        </if>
        <if test="author!=null">
            author=#{author},
        </if>
    </sql>

    <update id="updateByMap" parameterType="map">
       update blog
       <set>
           <include refid="ifstatment"></include>
       </set>
       where id=#{id}
    </update>


</mapper>

5foreach

如果我们要拼接一个select *from Blog where (id=1 or id=2 or id=3)这样的语句就这么写

collection=“ids” 代表我们要遍历ids

item=“id” 代表遍历出来的内容放到这里

open=“and (” separator=“or” close=")" 代表拼接

id=#{id} 代表内容

<select id="updateByMap" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <foreach collection="ids" item="id" open="and (" separator="or" close=")">
                id=#{id}
            </foreach>
        </where>
    </select>

动态sql就是拼接sql语句 我们只要保证sql语句正确 排列组合就可以了

12缓存

1一级缓存

什么是缓存 当第一次查询一条数据的时候会进入数据库拿 如果第二次还拿相同的东西就不用去数据库拿 存放到本地

1作用范围

1同一个sqlsession开启到关闭之间的那段代码 一级缓存是默认开启的 不可以关闭

2 缓存失效的情况

1查询不同的东西 #比如查询1号和2号 用户 他们的缓存是不一样的

2增删改操作 #因为可能改变了数据

3查询不同的Mapper.xml # 使用不同的xml 他们的sqlsession都不一样

4手动清理缓存 #sqlsession.clearCache()

2二级缓存

1因为一级缓存作用域太小 所以出现了二级缓存 二级缓存的作用域在整个namespace之间

2工作机制

​ 一个会话查询的一条数据 这个数据就会被放到数据的一级缓存中

​ 如果当前会话关闭了 一级缓存就没了 但我们想 会话关闭后一级缓存内容放入二级缓存中

​ 新的会话查询会查询二级缓存的内容

​ 不同的mapper查出的数据会放在自己对应的缓存(mapper)中

3在mybatis核心配置中显示的开启全局缓存 也就是二级缓存 如果不写出来 默认也是开启的

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

4在要是用二级缓存的mapper.xml中开启二级缓存

也可以写一些参数[

在这里插入图片描述

FIFO:先进先出策略

3测试

3.1如果没有开启二级缓存测试

在这里插入图片描述

3.2二级缓存开启之后

在这里插入图片描述

4缓存执行流程

在这里插入图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值