Mybatis接上一部分

目录

4.配置解析(重点)

1、核心配置文件

2、环境配置(environments)

3、属性(properties)

4、类型别名(typeAliases)

5、设置(settings)

6、其他配置

7、映射器(mappers)

生命周期

2、resultMap

6、日志

1、日志工厂

2、Log4j

7、分页

1、使用Limit分页

2、RowBouns分页

3、分页插件

8、注解开发

1、面向接口编程

2、使用注解开发

3、CRUD

9、多对一处理

测试环境搭建

按照查询嵌套处理

按照结果嵌套处理

10、一对多处理

按结果嵌套查询

按查询嵌套处理

小结

11、动态SQL

搭建环境

if

choose(when,otherwise)

trim(where,set)

SQL片段

foreach

缓存

简介


4.配置解析(重点)

1、核心配置文件

  • mybatis-config.xml

  • MyBatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息

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

注意点:

每一个都有位置顺序,需要按照规定的来进行配置(即按上面的顺序来进行配置设置和属性)

2、环境配置(environments)

Mybatis 可以配置成适应多种环境

不过要记住:尽管可以配置多个环境,但每个SqlSessionFactory实例只能选择一种环境

学会使用配置多套运行环境!

Mybatis默认的事务管理器就是JDBC,连接池:POOLED

3、属性(properties)

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

这是属性都是可外部配置且可动态替换的,既可以在典型的Java属性文件中配置,亦可通过properties元素的子元素来传递。【db.properties】

编写一个配置文件

db.properties

deiver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&userUnicode=true&characterEncoding=UTF-8
username=root
password=123456

引入配置文件

    <!--引入外部配置文件-->
    <properties resource="db.properties"/>
  • 可以直接引入外部文件

  • 可以在其中增加一些属性配置

  • 如果两个文件有同一个字段,优先使用外部配置文件的!

4、类型别名(typeAliases)

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

  • 存在的意义仅在于用来减少类完全限定名的冗余。

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

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

扫描实体类的包,它的默认别名就是为这个类的类名,首字母小写

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

在实体类比较少的时候,使用第一种,多的时候用第二种

第一种可以DIY别名,第二章则不行,如果非要改,需要在实体上增加注解

@Alias("user")
public class User {
}

5、设置(settings)

这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为

logImpl指定 MyBatis 所用日志的具体实现,未指定时将自动查找。SLF4J | LOG4J(3.5.9 起废弃) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
cacheEnabled全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。true | false
lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。true | false

6、其他配置

  • typeHandlers类型处理器

  • objectFactory对象工厂

  • plugins插件

    • mybatis-generator-core

    • mybatis-plus

    • 通用mapper

7、映射器(mappers)

MapperRegistry:注册实现

方式一:使用resource【t推荐使用】

    <!--方式一-->
    <mappers>
        <mapper resource="com/yy/mapper/UserMapper.xml"/>    
    </mappers>

方式二:使用class文件绑定

    <!--方式二-->
    <mappers>
        <mapper class="com.yy.dao.UserMapper"/>
    </mappers>

注意点:

  • 接口和他的Mapper配置文件必须同名

  • 接口和他的Mapper配置文件必须在同一个包下

方式三:使用扫描包进行注入绑定

    <mappers>
        <package name="com.yy.mapper"/>
    </mappers>

注意点:

  • 接口和他的Mapper配置文件必须同名

  • 接口和他的Mapper配置文件必须在同一个包下

练习:

  • 将数据库配置文件外部引入

  • 实体类别名

  • 保证UserMapper接口和UserMapper.xml改为一致,并且放在同一包下

8、生命周期

 

生命周期、作用域是至关重要的,因为错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder

  • 一旦创建了 SqlSessionFactory,就不再需要它了。

  • 局部变量

SqlSessionFactory

  • 想象为:数据库连接池

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例

  • 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”

  • SqlSessionFactory 的最佳作用域是应用作用域

  • 最简单的就是使用单例模式或者静态单例模式。

SqlSession

  • 连接到连接池的一个请求

  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

  • 用完就要进行关闭请求,否则资源浪费

 

这个里面的每一个Mapper都代表一个具体的业务

5、解决属性名和字段名不一致的问题

1、问题

数据库中的字段

 

测试实体类字段不一致的情况

public class User {
    private int id;
    private String name;
    private String password;
}
//类型处理器
// select id,name,pwd from mybatis.user where id = #{id}

解决方法:

  • 起别名

    <select id="getUserById" parameterType="int" resultType="com.yy.pojo.User">
        select id,name,pwd as password from mybatis.user where id = #{id}
    </select>

2、resultMap

结果集映射

id name pwd
id name password
    <!--结果集映射-->
    <resultMap id="UserMap" type="User">
        <!--column数据库中的字段,property实体类中的属性-->
        <result property="id" column="id"/>
        <result column="name" property="name"/>
        <result column="password" property="password"/>
    </resultMap>
    <select id="getUserById" resultMap="UserMap">
        select * from mybatis.user where id = #{id}
    </select>
  • resultMap 元素是 MyBatis 中最重要最强大的元素。

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

  • ResultMap最优秀的地方在于,虽然你已经对它相当了解了,但是根本就不需要显示地用到他们

6、日志

1、日志工厂

如果一个数据库操作,出现了异常,我们需要排错,日志就是最好的帮手

曾经:sout、debug

现在:日志工厂

STDOUT_LOGGING标准日志输出

在mybatis核心配置文件中,配置我们的日志

    <settings>
        //要保证和官网一样,不用写错了
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

2、Log4j

什么是Log4j

  • Log4j是Apache的一个开源项目

  • 通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程

  • 可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程

  • 可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

  1. 先导入Log4j的包

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

2.log4j.properties

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
​
#控制台输出的相关设置
log4j.apperder.console = org.apache.log4j.ConsoleAppender
log4j.apperder.console.Target = System.out
log4j.apperder.console.Threshold=DEBUG
log4j.apperder.console.layout= org.apache.log4j.PatternLayout
log4j.apperder.console.layout.ConversionPattern=[%c]-%m%n
​
#文件输出的相关配置
log4j.apperder.file = org.apache.log4j.RollingFileAppender
log4j.apperder.file.File =./log/yy/log
log4j.apperder.file.MaxFileSize = 10mb
log4j.apperder.file.Threshold = DEBUG
log4j.apperder.file.layout = org.apache.log4j.PatternLayout
log4j.apperder.file.layout.ConvertsionPattern = [%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
​
  1. 配置log4j为日志实现

    <settings>
        <!--LOG4J日志的实现-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>
  1. log4j的使用,直接测试运行

简单使用

  1. 在要使用Log4j的类中,导入包

  2. 日志对象,参数为当前类的class

static Logger logger = Logger.getLogger(UserDaoTest.class);
  1. 日志级别

    @Test
    public void testlog4j(){
​
        logger.info("info:进入了testLog4j");
        logger.debug("debug:进入了。。。");
        logger.error("error:进入了。。。。");
    }

7、分页

1、使用Limit分页

语法:SELECT * from user limit startIndex,pageSize;
SELECT * from user limit 3; #[0,n]
​

使用Mybatis实现分页,核心SQL

  1. 接口

    //分页
    List<User> getUserByLimit(Map<String,Object> map);
  2. Mapper.xml

<!--分页-->
<select id="getUserByLimit" parameterType="map" resultType="User">
    select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
  1. 测试

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

2、RowBouns分页

不再使用SQL实现分页

  1. 接口

List<User> getUserByRowBounds();
  1. mapper.xml

<select id="getUserByRowBounds" resultType="User">
    select * from mybatis.user
</select>
  1. 测试

@Test
public void getUserByRowBounds(){
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //通过RowBounds实现
    RowBounds rowBounds = new RowBounds(1,2);
​
    //通过java代码层面实现分页
    List<User> userList = sqlSession.selectList("com.yy.dao.UserMapper.getUserByRowBounds",null,rowBounds);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

3、分页插件

Mybatis PageHelper

8、注解开发

1、面向接口编程

根本原因:==解耦==(可扩展,提高复用,分层开发中,上层不用管具体的实现,大家都遵守共同的标准,使得开发变容易,规范性更好)

关于接口的理解

  • 接口从更深层次的理解,应是定义(规范,约束)与实现(名实分离的原则)的分离。

  • 接口的本身反映了系统设计人员对系统的抽象理解。

  • 接口应有两类:

    • 第一类是对一个个体的抽象,它可对应为一个抽象体(abstract class);

    • 第二类是对一个个体某一方面的抽象,即形成一个抽象面(interface);

  • 一个体有可能有多个抽象面。抽象体与抽象面是有区别的。

三个面向区别

  • 面向对象是指,我们考虑问题时,以对象为单位,考虑它的属性及方法

  • 面向过程是指,我们考虑问题时,以一个具体的流程(事务过程)为单位,考虑它的实现

  • 接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题,更多的体现就是对系统整体的架构

2、使用注解开发

  1. 注解在接口上实现

  1. 需要在核心配置文件中绑定接口

<mappers>
    <mapper class="com/yy/dao/UserMapper"/>
</mappers>
  1. 测试

本质:反射机制实现

底层:动态代理

Mybatis详细流程

 

 

3、CRUD

可以设置自动提交事务

        public static SqlSession getSqlSession(){
            
            return  sqlSessionFactory.openSession(true);
        }

编写接口,增加注释

public interface UserMapper {
​
    //方法存在多个参数,所有的参数前面必须加上@Param("id")注解
    @Select("select * from user where id = #{id}")
    User getUserByID(int id);
​
    @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})")
    int addUser(User user);
​
    @Delete("delete from user where id = #{id}")
    int deleteUser(int id);
}

测试类

【注意:我们必须要将接口注册绑定到我们的核心配置文件中!!!】

    public void test(){
        //第一步:获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //方式一:getMapper,获取SQL
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
         mapper.addUser(new User(8, "yyqx", "123456"));
        mapper.deleteUser(8);
        mapper.getUserByID(2);
        //关闭SqlSession
        sqlSession.close();
    }

9、多对一处理

测试环境搭建

  • 导入依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.28</version>
        </dependency>
  • 在实体类中添加代码注解

@Data
public class Student {
    private int id;
    private String name;
    //多对一
    private Teacher teacher;
}
​
@Data
public class Teacher {
​
    private int id;
    private  String name;
}
​
  • 编写Mapper接口,并定义方法

  • 编写对应Mapper接口的xml文件

按照查询嵌套处理

  • 编写xml文件

    <select id="getStudent" resultMap="StudentTeacher">
        select * from mybatis.student
    </select>
    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
​
    <select id="getTeacher" resultType="Teacher">
        select * from mybatis.teacher where id = #{id}
    </select>
  • 测试类

    @Test
    public void testStudent(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.getStudent();
        for (Student student : students) {
            System.out.println(
                    student
            );
        }
​
        sqlSession.close();
    }

按照结果嵌套处理

  • 编写xml文件

    <select id="getStudent2" resultMap="StudentTeacher2">
    select s.id sid,s.name sname , t.name tname
    from mybatis.student s,mybatis.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>
  • 测试类

    @Test
    public void testStudent2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.getStudent2();
        for (Student student : students) {
            System.out.println(
                    student
            );
        }
​
        sqlSession.close();
    }

10、一对多处理

按结果嵌套查询

  • 实体类编写

@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;
}
  • 接口方法

public interface TeacherMapper {
    public List<Teacher> getTeacher(int id);
}
  • 对应的xml配置文件

<select id="getTeacher" resultMap="TeacherStudent">
    <!--
   思路:
       1. 从学生表和老师表中查出学生id,学生姓名,老师姓名
       2. 对查询出来的操作做结果集映射
           1. 集合的话,使用collection!
               JavaType和ofType都是用来指定对象类型的
               JavaType是用来指定pojo中属性的类型
               ofType指定的是映射到list集合属性中pojo的类型。
   -->
    select s.id sid,s.name sname,t.name tname,t.id tid
    from mybatis.student s, mybatis.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>

测试类

    @Test
    public void testGetTeacher(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher.getName());
        System.out.println(teacher.getStudents());
        sqlSession.close();
    }

按查询嵌套处理

  • 接口实现类

public Teacher  getTeacher2(int id);
  • 对应的配置文件

    <select id="getTeacher2" resultMap="TeacherStudent2">
        select * from mybatis.teacher where id = #{id}
    </select>
​
    <resultMap id="TeacherStudent2" type="Teacher">
          <!--column是一对多的外键 , 写的是一的主键的列名-->
        <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>
  • 测试类

    @Test
    public void  testGetTeacher2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher2(1);
        System.out.println(teacher.getName());
        System.out.println(teacher.getStudents());
    }

小结

1、关联-association

2、集合-collection

3、所以association是用于一对一和多对一,而collection是用于一对多的关系

4、JavaType和ofType都是用来指定对象类型的

  • JavaType是用来指定pojo中属性的类型

  • ofType指定的是映射到list集合属性中pojo的类型。

注意说明:

1、保证SQL的可读性,尽量通俗易懂

2、根据实际要求,尽量编写性能更高的SQL语句

3、注意属性名和字段不一致的问题

4、注意一对多和多对一 中:字段和属性对应的问题

5、尽量使用Log4j,通过日志来查看自己的错误

11、动态SQL

什么是动态SQL:不同的条件下生成不同的SQL语句

  • 动态 SQL 是 MyBatis 的强大特性之一。

  • 借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

    • 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

创建一个mybatis基础项目

<setting name="mapUnderscoreToCamelCase" value="true"/>
//驼峰命名

实体类

@Data
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;//属性名和字段名不一致
    private int views;
}

新建了IDUtils

@SuppressWarnings("all")//抑制警告
public class IDUtils {
    public  static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }
​
    @Test
    public void  test(){
        System.out.println(IDUtils.getId());
    }
}

实体类接口

public interface BlogMapper {
    //插入数据
    int addBlog(Blog blog);
}

接口实现

<?xml version="1.0" encoding="UTF8" ?>
 <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yy.mapper.BlogMapper">
    <insert id="addBlog" parameterType="blog">
        insert into mybatis.blog (id,title,author,create_time,views)
        values(#{id},#{title},#{author},#{createTime},#{views});
    </insert>
</mapper>

测试类

@Test
public void addInitBlog(){
    SqlSession session = MybatisUtils.getSqlSession();
    BlogMapper mapper = session.getMapper(BlogMapper.class);
​
    Blog blog = new Blog();
    blog.setId(IDUtils.getId());
    blog.setTitle("Mybatis如此简单");
    blog.setAuthor("狂神说");
    blog.setCreateTime(new Date());
    blog.setViews(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);
​
    session.close();
}

if

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog where 1=1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>
    //查询博客
    List<Blog> queryBlogIF(Map map);
@Test
public void queryBlogIF() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    map.put("author","yy");
    map.put("title","hello");
    List<Blog> blogList = mapper.queryBlogIF(map);
    for (Blog blog : blogList) {
        System.out.println(blog);
    }
    sqlSession.close();
​
}

choose(when,otherwise)

<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from mybatis.blog
    <where>
        <choose>
            <when test="title != null">
                and title like #{title}
            </when>
            <when test=" author != null">
                and author like #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
​
</select>
@Test
public void queryBlogChoose() {

    SqlSession sqlSession = MybatisUtils.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    HashMap map = new HashMap();
    map.put("author", "yy");
    map.put("title", "hello");
    map.put("views",1);
    List<Blog> blogList = mapper.queryBlogChoose(map);
    for (Blog blog : blogList) {
        System.out.println(blog);
    }
    sqlSession.close();
}
  • 从上往下执行,并且只执行一个判断

trim(where,set)

<where>
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</where>
  • set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号

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

SQL片段

<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
       <include refid="if-title-author"></include>
       <!-- 在这里还可以引用其他的 sql 片段 -->
   </where>
</select>

注意:

①、最好基于 单表来定义 sql 片段,提高片段的可重用性

②、在 sql 片段中不要包括 where

foreach

将数据库中前三个数据的id修改为1,2,3;

需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

1、编写接口

List<Blog> queryBlogForeach(Map map);

2、编写SQL语句

<select id="queryBlogForeach" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!--
       collection:指定输入对象中的集合属性
       item:每次遍历生成的对象
       open:开始遍历时的拼接字符串
       close:结束时拼接的字符串
       separator:遍历对象之间需要拼接的字符串
       select * from blog where 1=1 and (id=1 or id=2 or id=3)
     -->
       <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
          id=#{id}
       </foreach>
   </where>
</select>

3、测试

@Test
public void testQueryBlogForeach(){
   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();
}

小结:其实动态 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好首先要写原生的 sql 语句出来,然后在通过 mybatis 动态sql 对照着改,防止出错。多在实践中使用才是熟练掌握它的技巧。

缓存

简介

1、什么是缓存 [ Cache ]?

  • 存在内存中的临时数据。

  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

2、为什么使用缓存?

  • 减少和数据库的交互次数,减少系统开销,提高系统效率。

3、什么样的数据能使用缓存?

  • 经常查询并且不经常改变的数据。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值