Mybatis个人学习笔记

本文全面介绍了MyBatis,包括其定义、获取方式、使用优势。详细阐述了第一个MyBatis程序的搭建,涵盖CRUD操作、配置文件设置、日志使用、分页方法等内容。还讲解了参数传递、返回类型处理、映射关系及缓存机制等,为使用MyBatis开发提供了完整指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.介绍

1.1 什么是MyBatis?

  • MyBatis 是一款优秀的持久层框架
  • 它支持自定义 SQL、存储过程以及高级映射
  • MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

1.2 如何获取MyBatis?

  • Maven仓库

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.6</version>
    </dependency>
    
  • GitHub:https://github.com/mybatis/mybatis-3

  • 中文网文档:https://mybatis.org/mybatis-3/zh/index.html

1.3 数据持久化:程序的数据由瞬时状态转化为持久状态的过程

1.4 持久层:完成持久化工作的代码块

1.5 为什么需要MyBatis?

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射
  • 提供对象关系映射标签,支持对象关系组建维护
  • 提供xml标签,支持编写动态sql。

2.第一个MyBatis程序

思路:搭建环境->导入Mybatis->编写代码->测试

2.1搭建环境

  • 创建数据库和表

    CREATE DATABASE mybatis1;
    
    USE mybatis1
    
    CREATE TABLE users(
    	uid INT PRIMARY KEY,
    	uname VARCHAR(32),
    	uaccount VARCHAR(32),
    	upwd VARCHAR(32)
    )
    
  • 导入依赖

    <!--导入依赖-->
        <dependencies>
            <!--msql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
    
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.6</version>
            </dependency>
        </dependencies>
    
  • 创建包

  • 创建实体类

    public class Users implements Serializable {
        private long uid;
        private String uname;
        private String uaccount;
        private String upwd;
    
        public Users() {
        }
    
        public Users(long uid, String uname, String uaccount, String upwd) {
            this.uid = uid;
            this.uname = uname;
            this.uaccount = uaccount;
            this.upwd = upwd;
        }
    
        public long getUid() {
            return uid;
        }
    
        public void setUid(long uid) {
            this.uid = uid;
        }
    
        public String getUname() {
            return uname;
        }
    
        public void setUname(String uname) {
            this.uname = uname;
        }
    
        public String getUaccount() {
            return uaccount;
        }
    
        public void setUaccount(String uaccount) {
            this.uaccount = uaccount;
        }
    
        public String getUpwd() {
            return upwd;
        }
    
        public void setUpwd(String upwd) {
            this.upwd = upwd;
        }
    
        public String toString() {
            return "Users{" +
                    "uid=" + uid +
                    ", uname='" + uname + '\'' +
                    ", uaccount='" + uaccount + '\'' +
                    ", upwd='" + upwd + '\'' +
                    '}';
        }
    }
    
  • 创建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>
    
        <!--加载外部配置文件-->
        <properties resource="db.properties"/>
        
        <settings>
            <setting name="logImpl" value="LOG4J"/>
        </settings>
        
        <typeAliases>
            <package name="com.codewen.entity"/>
        </typeAliases>
    
        <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/codewen/mapper/UsersMapper.xml"/>
        </mappers>
    
    </configuration>
    
  • 创建获取SQLSession的工具类

    public class SqlSessionUtil {
    
        private static SqlSessionFactory sqlSessionFactory;
        static {
            String resource = "mybatis-config.xml";
            try {
                InputStream is = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static SqlSession getSession() {
            return sqlSessionFactory.openSession();
        }
    }
    
    
  • 创建mapper

    public interface UsersMapper {
        List<Users> queryAllUsers();
    }
    
  • 创建mapper对应的xml

    <?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.codewen.mapper.UsersMapper">
    
        <select id="UsersMapper" resultType="com.codewen.entity.Users">
          SELECT * FROM users
        </select>
    
    </mapper>
    
  • 创建测试类

    public class Test01 {
        public static void main(String[] args) {
            SqlSession session = SqlSessionUtil.getSession();
            UsersMapper mapper = session.getMapper(UsersMapper.class);
            List<Users> users = mapper.queryAllUsers();
            for(Users user : users) {
                System.out.println(user);
            }
        }
    }
    

    此时运行后会发现一个异常 这是没有在mybatis配置文件中注册mapper的原因

  • 注册mapper(有三种resource、class、url)

    <mappers>
            <mapper resource="com/codewen/mapper/UsersMapper.xml"/>
            <!--<mapper class="com.codewen.mapper.UsersMapper"/>-->
        </mappers>
    

2.3运行结果

2.4资源过滤问题

如果遇到写的配置文件无法导入或者不生效的问题 可能是资源过滤问题

出现原因:配置文件没有放到resources目录下

image-20210109143737306

解决方法(在pom.xml中设置resources文件):

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

3.CRUD

3.1 namespace中的包名要和dao接口全限定名一致

步骤(注意增删改需要提交事务):

  • 在dao层接口中先写方法
  • 再到mapper.xml中写对应的sql
  • 直接进行测试即可

3.2 select

  • id:就是namespace对应接口中的方法
  • resultType:SQL语句执行的返回值类型 只有引用类型(必须写全限定类名)和基本类型
  • parameterType:参数类型
// 查询所有用户
    List<Users> queryAllUsers();

    // 查询一个用户
    Users queryUser(int uid);
<select id="queryAllUsers" resultType="com.codewen.entity.Users">
      SELECT * FROM users
    </select>

    <select id="queryUser" resultType="com.codewen.entity.Users">
        select * from users where uid=#{uid};
    </select>

3.3 insert

// 增加一个用户
    int insertUser(Users user);
<insert id="insertUser" parameterType="com.codewen.entity.Users">
        insert into users (uname,uaccount,upwd) values (#{uname},#{uaccount},#{upwd});
    </insert>

3.4 delete

// 删除一个用户
    int deleteUser(int uid);
<delete id="deleteUser" parameterType="int">
        delete from users where uid = #{uid};
    </delete>

3.5 update

// 修改一个用户
    int updateUser(Users user);
<update id="updateUser" parameterType="com.codewen.entity.Users">
        update users set uname=#{uname}, upwd=#{upwd} where uid=#{uid};
    </update>

3.6关于传参

  • map传递参数在sql中只需要通过key即可取出值 parameterType=“map”
  • 对象传递参数在sql中必须对应对象属性才能取出值 parameterType=“object”
  • 如果传递参数是一个基本数据类型如int,那么parameterType可以省略不写
  • 但如果传递参数是多个,那么必定不能省略不写,可以用map或者注解@Param

4.配置文件

4.1核心配置文件mybatis-config.xml(标签的顺序有先后,必须按照下面顺序排列)

4.2 环境配置environments

<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/mybatis1"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
    </environments>
  • environments的default属性表示选择的默认环境
  • mybatis中的事务类型有两种,一种是JDBC,另一种是managed
  • mybatis中的数据源类型有三种 POOLED、UNPOOLED、JNDI

4.3 属性properties

没有引用外部properties文件之前

<property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis1"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>

引入外部properties文件之后

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis1
username=root
password=123
<?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 resource="db.properties"/>
	<!--设置日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

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


</configuration>

4.4 typeAliases

第一种:typeAlias type时指定实体类的全限定类名 alias是别名(这种方式适合实体类较少的情况,取别名方便)

<typeAlias type="com.codewen.entity.Users" alias="user"/>

第二种:package name是实体类所在的包名(这种方式适合实体类较多的情况)

这种方式的别名就是实体类名的小写,当然也可以用大写,建议用小写

<package name="com.codewen.entity"/>

但是这种方式不能为其它别名,如果想改其它别名,得用到注解

@Alias("uuu")

4.5 设置settings

常见的设置

  • cacheEnabled 使用缓存 默认为true
  • lazyLoadingEnabled 懒加载 默认为false
  • mapUnderscoreToCamelCase 驼峰命名 默认为false
  • logImpl 指定日志实现 如log4j 默认无

4.6 插件plugins

  • mybatis-generator-core
  • mybatis-plus (mybatis简化版)
  • 通用mappers

4.7 映射器mappers

有四种 resources、url、class、name(url不要去用)

方式一(推荐使用):

<mapper resource="com/codewen/mapper/UsersMapper.xml"/>

方式二:

<mapper class="com.codewen.mapper.UsersMapper"/>

注意点

  • 接口和mapper.xml必须同名
  • 接口和mapper.xml必须在同一个包或者在resources中相同的包

方式三:

<package name="com.codewen.mapper"/>

注意点

  • 接口和mapper.xml必须同名
  • 接口和mapper.xml必须在同一个包或者在resources中相同的包

4.8 生命周期和作用域

  • SqlSessionFactory 相当于连接池
  • SqlSession 相当于一个会话(请求)
  • mapper 相当于一个具体的业务

5.日志

5.1 日志工厂

曾经:sout、控制台

现在:LOG4J、STDOUT_LOGGING…

5.2 stdout_logging(注意name和value大小写别写错!)

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

5.3 log4j

第一步:导入log4j依赖或包

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

第二步:创建log4j.properties

#将等级为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/codewen.log
log4j.appender.file.MaxFileSize=5mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd HH:mm:ss}][%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

第三步:mybatis-config.xml中开启日志(注意name和value大小写别写错!)

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

5.4 log4j的一般使用方法

static Logger logger = Logger.getLogger(Test1.class);
@Test
public void test2() {
	logger.info("这是info级别日志");
	logger.debug("这是debug级别日志");
	logger.error("这是error级别日志");
}

6.属性名和字段名不匹配

第一种:修改sql语句,将sql中列的字段名取别名为属性名

第二种:使用resultMap,只需要映射不同的

    <resultMap id="allUsersMap" type="users">
        <result column="uid" property="id"/>
    </resultMap>

    <select id="queryAllUsers" resultMap="allUsersMap">
      SELECT * FROM users
    </select>

7.分页

7.1 使用limit分页

语法:

-- 分页 select * from stu limit  开始索引=(当前页面-1)*页面大小,页面大小;
SELECT * FROM stu LIMIT 0,5;
SELECT * FROM stu LIMIT 5,5;
SELECT * FROM stu ORDER BY id LIMIT 0,5;-- 可以先进行排序然后再分页显示

7.2 使用Rowbounds分页

// 使用Rowbounds分页
List<Users> queryAllUsersByRB();
<select id="queryAllUsersByRB" resultType="users">
	SELECT * FROM users;
</select>
 List<Users> users = sqlSession.selectList("com.codewen.mapper.UsersMapper.queryAllUsersByRB", null, new RowBounds(0, 2));

7.3 mybatis分页插件 PageHelper(需要时直接看文档使用)

8.sql语句中获取参数值

第一种:${} 这种方法不推荐,有SQL注入的风险,原样输出,但是还是适合于动态排序(动态字段)

第二种:#{} 预编译,可以有效防止SQL注入 会自动给String类型加上’'

9.Lombok使用

使用步骤:

第一步:下载lombok插件


第二步:导入jar包/依赖

<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>

第三步:创建实体类,利用注解使用

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String account;
    private String pwd;
}

@Data:getter、setter、toString、equals、hashCode

@NoArgsConstructor:无参构造器

@AllArgsConstructor:有参构造器

10.映射

10.1 一对一association(javaType是属性的类型)

比如一个学生对应一个老师

第一种:按照结果进行嵌套

首先搭建数据库环境

# 创建数据库
CREATE DATABASE mybatis2;

# 创建学生表
CREATE TABLE student (
	sno INT PRIMARY KEY AUTO_INCREMENT, -- 主键
	sname VARCHAR(32),
	sage INT,
	s_tname VARCHAR(32)
);

# 创建教师表
CREATE TABLE teacher (
	tno INT PRIMARY KEY AUTO_INCREMENT, -- 主键
	tname VARCHAR(32) UNIQUE
);

# 添加外键约束及级联更新
ALTER TABLE student ADD CONSTRAINT s_tno_fk FOREIGN KEY(s_tno) REFERENCES teacher(tno) ON UPDATE CASCADE ON DELETE CASCADE;

# 插入数据
INSERT INTO teacher (tname,ttype) VALUES ('uzi','生物');
INSERT INTO teacher (tname,ttype) VALUES ('zs','语文');
INSERT INTO teacher (tname,ttype) VALUES ('ls','数学');

INSERT INTO student (sname,sage,s_tno) VALUES ('小红',17,3);
INSERT INTO student (sname,sage,s_tno) VALUES ('小龙',19,3);
INSERT INTO student (sname,sage,s_tno) VALUES ('小刚',18,2);
INSERT INTO student (sname,sage,s_tno) VALUES ('小李',16,3);
INSERT INTO student (sname,sage,s_tno) VALUES ('小赵',20,2);
INSERT INTO student (sname,sage,s_tno) VALUES ('小陈',18,1);
INSERT INTO student (sname,sage,s_tno) VALUES ('小宋',18,1);
INSERT INTO student (sname,sage,s_tno) VALUES ('老王',21,2);

# 级联查询
SELECT * FROM student,teacher WHERE student.s_tno=teacher.tno

然后组合教师类

    private Teacher teacher;

最后根据返回结果进行属性和列的一一映射(注意映射了的属性才能获取值)

    <resultMap id="student_teacher_map" type="student">
        <id property="sno" column="sno"/>
        <result property="sname" column="sname"/>
        <result property="sage" column="sage"/>
        <association property="teacher" javaType="teacher">
            <id property="tno" column="tno"/>
            <result property="tname" column="tname"/>
            <result property="ttype" column="ttype"/>
        </association>
    </resultMap>
    
    <select id="queryAllStudent2" resultMap="student_teacher_map">
        SELECT *
        FROM student,teacher
        WHERE student.s_tno=teacher.tno
    </select>

第二种:子查询的方式

不同之处是mapper.xml处编写不同

<!--第二种一对一关联查询-->
    <select id="queryTeacher" resultType="teacher">
        select * from teacher where tno=#{tno}
    </select>

    <resultMap id="student_teacher_map2" type="student">
        <id property="sno" column="sno"/>
        <result property="sname" column="sname"/>
        <result property="sage" column="sage"/>
        <result property="s_tno" column="s_tno"/>
        <association property="teacher" column="s_tno" javaType="teacher" select="queryTeacher"/>
    </resultMap>

    <select id="queryAllStudent3" resultMap="student_teacher_map2">
        SELECT *
        FROM student
    </select>

10.2 一对多collection(注意ofType是属性中元素的类型)

比如一个老师对应一个学生

    private List<Student> students;

sql语句

SELECT * FROM student,teacher WHERE student.s_tno=teacher.tno AND tno=1

mapper.xml文件

<select id="queryAllStudentByTno" resultMap="teacher_student_map">
	SELECT *
	FROM student,teacher
	WHERE student.s_tno=teacher.tno AND tno=#{tno};
</select>

<resultMap id="teacher_student_map" type="teacher">
    <id property="tno" column="tno"/>
    <result property="tname" column="tname"/>
    <result property="ttype" column="ttype"/>
    <collection property="students" ofType="student">
    	<id property="sno" column="sno"/>
        <result property="sname" column="sname"/>
        <result property="sage" column="sage"/>
    </collection>
</resultMap>

11.动态sql及标签

11.1 sql标签与include标签

使用sql标签可以实现复用sql,id为该sql语句的名称

<sql id="queryAllBooks">
    select * from book;
</sql>

sql标签跟include标签进行sql复用

<include refid="queryAllBooks"/>

11.2 if标签

if标签用法和java中的if很相似,test属性中是判断的内容

<if test="btime != null">
    btime=#{btime}
</if>
<if test="author_array != null and author_array[0] != null">
    and bauthor=#{author_array[0]}
</if>

11.3 where标签

where标签用来替代sql中传统的where,一般配合if标签使用

where标签的作用:

  • 如果where后面没有语句,那么最后的sql不会把where加上
  • 如果where后面有语句,那么会把第一个语句的and去掉
SELECT * FROM book
<where>
    <if test="btime != null">
        btime=#{btime}
    </if>
    <if test="author_array != null and author_array[0] != null">
        and bauthor=#{author_array[0]}
    </if>
</where>

11.4 set标签

set标签用来替代sql中传统的set,一般配合if标签使用

set标签的作用:用于update的sql中,会把末尾多余的逗号去掉

update book
<set>
    <if test="bname!=null and bname!=''">
        bname=#{bname},
    </if>
    <if test="bauthor!=null and bauthor!=''">
        bauthor=#{bauthor},
    </if>
    <if test="bintroduction!=null and bintroduction!=''">
        bintroduction=#{bintroduction}
    </if>
</set>
...

11.5 trim标签

<trim prefix="" prefixOverrides="" suffix="" suffixOverrides=""></trim>

prefix:为标签下的sql语句加一个前缀

prefixOverrides:标签下的sql语句前面多了可以去掉

suffix:为标签下的sql语句加一个后缀

suffixOverrides:标签下的sql语句后面多了可以去掉

<trim prefix="ORDER BY" suffixOverrides="," suffix="desc">
    <!-- 时间排序 -->
    <if test="conditionMap.byTime !=null and conditionMap.byTime !='' ">
        btime,
    </if>
    <!-- 字数排序 -->
    <if test="conditionMap.byWord !=null and conditionMap.byWord !='' ">
        totalwords,     
    </if>
    <!-- 阅读数排序 -->
    <if test="conditionMap.byRead !=null and conditionMap.byRead !='' ">
        readtimes,     
    </if>
</trim>

这个例子中**suffixOverrides=","**就是把suffixOverrides:标签下的sql语句后面多余的逗号去掉

11.6 bind标签

bind标签就相当于在value值中,把需要的字符拼接好,然后用name中的值去代替拼接好的参数。(一般用于与#{}取值拼接)

使用 bind 拼接字符串不仅可以避免因更换数据库而修改 SQL,也能预防 SQL 注入。

<bind name="bindfparam" value=" '%'+ parameterMap.fparam +'%' "/>
concat(bname,bauthor,bcategory) like #{bindfparam}

11.7 foreach标签

foreach标签可以迭代对象的属性、数组、集合、对象数组、对象集合,构建in条件语句或者批量操作语句

<foreach collection="" item="" open="" close=""  separator="" index=""/>

collection:表示要迭代的对象的属性、数组、集合、对象数组、对象集合

item:collection中要迭代的单个元素

open:表示该段语句以什么开头

close:表示该语句以什么结尾

separator:表示该语句以什么划分

index:在list、Set和数组中,index表示当前迭代的位置,在map中,index代指是元素的key,一般不用

注意点:

  • 如果要迭代的是数组(简单类型的或者对象类型的都一样) collection中必须是array
// 通过bnum的in条件查询书籍
List<Book> queryBookByBIN(int[] bnums);
<!--通过bnum的in条件查询书籍-->
    <select id="queryBookByBIN" resultType="book">
        select * from book
        <where>
            bnum
            <foreach collection="array" item="bnum" open=" in(" close=");" separator=",">
              #{bnum}
            </foreach>
        </where>
    </select>
  • 如果要迭代的是集合,collection必须是list
List<Book> queryBookByBIN(List bnums);
<!--通过bnum的in条件查询书籍-->
<select id="queryBookByBIN" resultType="book">
    select * from book
    <where>
        bnum
        <foreach collection="list" item="bnum" open=" in(" close=");" separator=",">
            #{bnum}
        </foreach>
    </where>
</select>
  • 如果要迭代的是对象,collection直接为对象中的属性即可

12.关于传参

12.1 如果传入的参数只有一个

parameterType可以不写(这里其实parameterType可以随意写,只要是可以识别的)

// 传入的是一个对象
int addBook(Book book);

// 那么parameterType要写的话就写该对象的类型
parameterType="book"
// 传入的是一个基本数据类型
List<Book> queryBookByBnum(int bnum);

// 要写的话就写对应的基本数据类型
parameterType="int"

12.2 如果传入的参数是两个及以上(要使用@Param来命名参数)

parameterType就没必要写了

// 通过btime和bauthor查询书籍
List<Book> queryBookByTA(String btime, String bauthor);
<!--通过btime和bauthor查询书籍-->
<select id="queryBookByTA" resultType="book">
    SELECT * FROM book
    <where>
        <if test="btime != null">
            btime=#{btime}
        </if>
        <if test="bauthor != null">
            and bauthor=#{bauthor}
        </if>
    </where>
</select>

可以看到这样无法识别传入的参数,要使用@Param来命名参数,取的时候直接取命名的即可

List<Book> queryBookByTA(@Param("btime") String btime,@Param("bauthor") String bauthor);

12.3 关于其他类型的传参及取值

如果参数中有map(可以通过#{map.键}取值)

List<Book> queryBookByTA(@Param("btime") String btime,@Param("author_map") Map author_map);
<!--通过btime和bauthor查询书籍-->
<select id="queryBookByTA" resultType="book">
    SELECT * FROM book
    <where>
        <if test="btime != null">
            btime=#{btime}
        </if>
        <if test="author_map != null and author_map.bauthor != null">
            and bauthor=#{author_map.bauthor}
        </if>
    </where>
</select>

如果传入的参数有list(可以通过#{list[i]}取值)

List<Book> queryBookByTA(@Param("btime") String btime,@Param("author_list") List author_list);
 <!--通过btime和bauthor查询书籍-->
<select id="queryBookByTA" resultType="book">
    SELECT * FROM book
    <where>
        <if test="btime != null">
            btime=#{btime}
        </if>
        <if test="author_list.size>0 and author_list[0] != null">
            and bauthor=#{author_list[0]}
        </if>
    </where>
</select>

如果传入的参数有数组(类似list取值)

List<Book> queryBookByTA(@Param("btime") String btime,@Param("author_array") String[] author_array);
<!--通过btime和bauthor查询书籍-->
<select id="queryBookByTA" resultType="book">
    SELECT * FROM book
    <where>
        <if test="btime != null">
            btime=#{btime}
        </if>
        <if test="author_array != null and author_array[0] != null">
            and bauthor=#{author_array[0]}
        </if>
    </where>
</select>

13.关于返回类型

13.1 如果返回的不是复杂类型要使用resultType

不是复杂类型:基本数据类型、JavaBean、map、list、数组… resultType中是MyBatis内置Java类型对应的别名

13.2 如果返回值类型是复杂类型(要用resultMap来进行属性和字段的映射)

如:字段名与属性名不一致需要重新映射(即实体类的属性与数据库的字段不一致时) 主键用 其他字段用

<id property="tno" column="tno"/>
<result property="tname" column="tname"/>
<result property="ttype" column="ttype"/>

​ 若存在一对一或者一对多的复杂关系映射 可见10.映射

14.缓存

14.1 一级缓存 sqlSession级别的缓存,默认是开启的

失效的情况:

  • sqlSession不同
  • sqlSession相同,查询不同
  • 手动清除了一级缓存
  • sqlSession相同,两次相同查询之间进行了增删改

14.2 二级缓存

开启二级缓存步骤:

第一步:显式开启全局配置

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

第二步:mapper.xml中增加cache标签

cache中的一些参数

第三步:实体类都要实现可序列化接口

注意点:

  • 每个select标签都有useCache=“true” 跟二级缓存有关,一级缓存不受影响
  • useCache=“true” 开启二级缓存,但如果全局配置没开启二级缓存(cacheEnabled=false),useCache就没用

14.3 缓存原理

首先,查询会先看二级缓存中有没有,如果没有再看一级缓存,一级缓存也没有就查数据库,查到了后把结果放到一级缓存,待当前会话结束后,一级缓存中的缓存数据会转移到二级缓存中

14.4 自定义缓存

创建一个类实现org.apache.ibatis.cache.Cache接口即可

14.5 第三方提供的二级缓存ehcache

第一步:导入依赖或包

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.0.0</version>
</dependency>

第二步:

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

第三步:创建ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    
    <diskStore path="./tmpdir/Tmp_EhCache"/>

    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>

    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
</ehcache>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codewen77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值