Mybatis(一) Mybatis入门详解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/xuruanshun/article/details/102684879

目录

1.原生的Jdbc编程

2.Mybatis介绍

3.Mybatis架构

4.Mybatis入门

5.JDBC,Mybatis,hibernate浅谈

6.映射文件 Mapper.xml详解

7.SqlMapConfig.xml配置文件详解

8.缓存(了解)

9.延迟加载(了解)

10.分页插件

 

 

1.原生的Jdbc编程

1.1.Jdbc编程步骤

  1. 加载数据库驱动
  2. 创建并获取数据库链接
  3. 创建jdbc statement对象
  4. 设置sql语句
  5. 设置sql语句中的参数(使用preparedStatement)
  6. 通过statement执行sql并获取结果
  7. 对sql执行结果进行解析处理
  8. 释放资源(resultSet、preparedstatement、connection)

使用原生的jdbc方式实现与数据库交互:

public static void main(String[] args) {
	Connection connection = null;
	PreparedStatement preparedStatement = null;
	ResultSet resultSet = null;

	try {
		// 加载数据库驱动
		Class.forName("com.mysql.jdbc.Driver");

		// 通过驱动管理类获取数据库链接
		connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", "root");
		// 定义sql语句 ?表示占位符
		String sql = "select * from user where username = ?";
		// 获取预处理statement
		preparedStatement = connection.prepareStatement(sql);
		// 设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
		preparedStatement.setString(1, "王五");
		// 向数据库发出sql执行查询,查询出结果集
		resultSet = preparedStatement.executeQuery();
		// 遍历查询结果集
		while (resultSet.next()) {
			System.out.println(resultSet.getString("id") + "  " + resultSet.getString("username"));
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		// 释放资源
		if (resultSet != null) {
			try {
				resultSet.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (preparedStatement != null) {
			try {
				preparedStatement.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

1.2.jdbc问题总结:

  1. 数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。
  2. Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。
  3. 使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。
  4. 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

2.Mybatis介绍

 

 

3.Mybatis架构

1)mybatis配置文件:

     SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。

     mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。

2)通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂

3)由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。

4)mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。

5)Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql        对应一个Mapped Statement对象,sql的id即是Mapped statement的id。

6)Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行        sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。

7)Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行       sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。

4.Mybatis入门

4.1.搭建环境

1.在数据库创建一张user表,并插入一条数据。

CREATE TABLE `user` (
	`id` int(11) NOT NULL AUTO_INCREMENT,
	`username` varchar(32) NOT NULL COMMENT '用户名称',
	`birthday` date DEFAULT NULL COMMENT '生日',
	`sex` char(1) DEFAULT NULL COMMENT '性别',
	`address` varchar(256) DEFAULT NULL COMMENT '地址',
	PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8



insert into `user` (`id`, `username`, `birthday`, `sex`, `address`) values('1','张飞','2002-08-01','男','北京');

2.idea创建一个maven的简单Java项目

注:idea创建maven的Java项目方式可参考文档:https://blog.csdn.net/qq_32296307/article/details/78432581

3.pom文件添加依赖

<?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>com.dayee.cn</groupId>
    <artifactId>MybatisDemo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- Mybatis 依赖 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.0</version>
        </dependency>

        <!-- MySQL数据库依赖 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

        <!--junit测试包-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>

4.entity目录下的实体类User.java

package com.dayee.entity;


import java.util.Date;

public class User {

    // ID
    private Integer id;
    // 姓名
    private String username;
    // 性别
    private String sex;
    // 生日
    private Date birthday;
    // 地址
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday=" + birthday +
                ", address='" + address + '\'' +
                '}';
    }
}

5.在resources目录下,创建一个SqlMapConfig.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>
    <!-- 和spring整合后 environments配置将废除 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用jdbc事务管理 -->
            <transactionManager type="JDBC" />
            <!-- 数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8" />
                <property name="username" value="root" />
                <property name="password" value="123" />
            </dataSource>
        </environment>
    </environments>
</configuration>

注:SqlMapConfig.xml是mybatis核心配置文件,配置文件内容为数据源、事务管理。

       和spring整合之后,SqlMapConfig.xml就不会配置数据源信息,都会放在spring配置文件上,此文件主要加载mapper文件。

 

6.在resources目录下创建sqlmap目录,此目录下放置的都是实体类对应的mapper.xml文件。创建UserMapper.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">
<!-- namespace:命名空间,用于隔离sql,必须唯一,还有一个很重要的作用,后面会讲 -->
<mapper namespace="test">



</mapper>

 

7.在SqlMapConfig.xml文件中加载UserMapper.xml文件

4.2.示例:实现根据id查询用户

使用的sql:   

SELECT * FROM `user` WHERE id = 1

 

1.编辑UserMapper.xml映射文件

<mapper namespace="test">

    <!-- id:statement的id 或者叫做sql的id-->
    <!-- parameterType:声明输入参数的类型 -->
    <!-- resultType:声明输出结果的类型,应该填写pojo的全路径 -->
    <!-- #{}:输入参数的占位符,相当于jdbc的? -->
    <select id="queryUserById" parameterType="int" resultType="com.dayee.entity.User">
      SELECT * FROM `user` WHERE id  = #{id}
   </select>

</mapper>

注意:

1)parameterType可省略,但是不建议省略。

2)在<select>标签中,resultType和resultMap必须选择其中一个,

    当实体类属性名称与表字段名称不相同时,可以使用resultMap定义其对应关系,并且获得这个属性。

     如果都相同,或者有不相同,我既不使用这个字段,也不获得这个字段,也可以使用resultType,后文有详解。

 

2.测试:MybatisTest.java

测试程序步骤:

1)创建SqlSessionFactoryBuilder对象

 2) 加载SqlMapConfig.xml配置文件

 3. 创建SqlSessionFactory对象

 4. 创建SqlSession对象

 5. 执行SqlSession对象执行查询,获取结果User

 6. 打印结果

 7. 释放资源

package com.dayee;

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 org.junit.Before;
import org.junit.Test;

import java.io.InputStream;

public class MybatisTest {
    private SqlSessionFactory sqlSessionFactory = null;

    @Before
    public void setUp() throws Exception {
        // 1. 创建SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

        // 2. 加载SqlMapConfig.xml配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");

        // 3. 创建SqlSessionFactory对象
        this.sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
    }

    @Test
    public void testQueryUserById() throws Exception {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行查询,获取结果User
        // 第一个参数是User.xml的statement的id,第二个参数是执行sql需要的参数;
        Object user = sqlSession.selectOne("test.queryUserById", 1);

        // 6. 打印结果
        System.out.println(user);

        // 7. 释放资源
        sqlSession.close();

    }
}

注意:

namespace作区分标识使用,在多个namespace中没有相同的id时,selectOne的第一个参数可以省略namespace

也就是说 test.queryUserById 可以省略test,写作queryUserById,但是不建议省略。

 

3.控制台效果:

 

4.别名方式:解决字段名和属性名不一致的问题

如果字段名称和属性名称不相同,有两种解决方式:

第一种是使用resultMap,后文详解;第二种就是使用别名的方式,此处解释。

 

 

4.3.示例:实现根据用户名模糊查询用户

查询sql:

SELECT * FROM `user` WHERE username LIKE '%张%'

 

方法一:使用#{}

1.编辑UserMapper.xml映射文件

<!-- 如果返回多个结果,mybatis会自动把返回的结果放在list容器中 -->
<!-- resultType的配置和返回一个结果的配置一样 -->
<select id="queryUserByUsername1" parameterType="string" resultType="com.dayee.entity.User">
   SELECT * FROM `user` WHERE username LIKE #{username}
</select>

2.测试:MybatisTest.java

    @Test
    public void testQueryUserByUsername1() throws Exception {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行查询,获取结果User
        // 查询多条数据使用selectList方法
        List<Object> list = sqlSession.selectList("queryUserByUsername1", "%张%");

        // 6. 打印结果
        for (Object user : list) {
            System.out.println(user);
        }

        // 7. 释放资源
        sqlSession.close();
    }

3.控制台效果:

方法二:使用${}

1.编辑UserMapper.xml映射文件

<!-- 如果传入的参数是简单数据类型,${}里面必须写value -->
<select id="queryUserByUsername2" parameterType="string" resultType="com.dayee.entity.User">
   SELECT * FROM `user` WHERE username LIKE '%${value}%'
</select>

2.测试:MybatisTest.java

    @Test
    public void testQueryUserByUsername2() throws Exception {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行查询,获取结果User
        // 查询多条数据使用selectList方法
        List<Object> list = sqlSession.selectList("queryUserByUsername2", "%张%");

        // 6. 打印结果
        for (Object user : list) {
            System.out.println(user);
        }

        // 7. 释放资源
        sqlSession.close();
    }

3.控制台效果:

注:

1)selectOne和selectList的区别:

     selectOne查询一条记录,如果使用selectOne查询多条记录则抛出异常;而selectList可以查询一条或多条记录。

4.4. #{} 和 ${} 的区别

#{}表示占位符,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换。有效防止sql注入。 

#{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。

 

${}表示字符串拼接,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换;

${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。

 

${}不能防止sql注入,尽量少用,使用#{}代替。

详细内容可以参考:https://blog.csdn.net/xuruanshun/article/details/102697921

 

 

4.5.示例:实现添加用户

4.5.1.示例

使用的sql:

INSERT INTO `user` (username,birthday,sex,address) VALUES ('黄忠','2016-07-26','1','三国')

1.编辑UserMapper.xml映射文件

   <!-- 保存用户 -->
   <insert id="saveUser" parameterType="com.dayee.entity.User">
       INSERT INTO `user`
       (username,birthday,sex,address) VALUES
       (#{username},#{birthday},#{sex},#{address})
   </insert>

2.测试:MybatisTest.java

    @Test
    public void testSaveUser() {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行保存
        // 创建需要保存的User
        User user = new User();
        user.setUsername("黄忠");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("蜀国");

        sqlSession.insert("saveUser", user);
        System.out.println(user);

        // 需要进行事务提交
        sqlSession.commit();

        // 7. 释放资源
        sqlSession.close();
    }

注意:CRUD操作时,只有查询可以不用commit (提交事务),增删改都需要commit,CRUD都需要close(释放资源);

3.控制台效果:

如上所示,保存成功,但是id=null,需要解决id返回不正常的问题。

4.5.2.Mysql使用主键自增(方式一)

查询id的sql:

 SELECT LAST_INSERT_ID()

1.通过修改UserMapper.xml映射文件,可以将mysql自增主键返回:如下添加selectKey 标签

<!-- 保存用户 -->
   <insert id="saveUser" parameterType="com.dayee.entity.User">
       <!-- selectKey 标签实现主键返回 -->
       <!-- keyColumn:主键对应的表中的哪一列 -->
       <!-- keyProperty:主键对应的pojo中的哪一个属性 -->
       <!-- order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql -->
       <!-- resultType:设置返回的id的类型 -->
       <selectKey keyColumn="id" keyProperty="id" order="AFTER" resultType="int">
           SELECT LAST_INSERT_ID()
       </selectKey>

       INSERT INTO `user`
       (username,birthday,sex,address) VALUES
       (#{username},#{birthday},#{sex},#{address})
</insert>

LAST_INSERT_ID():是mysql的函数,返回auto_increment自增列新记录id值。

2.控制台效果:

4.5.3.Mysql使用主键自增(方式二)

<!-- 
        useGeneratedKeys:开启自增id回填
        keyColumn:指定数据库表中列名
        keyProperty:指定对象中的属性名
        如果keyColumn=keyProperty,keyColumn可以省略不写
     -->
    <insert id="saveUser2" parameterType="com.dayee.entity.User" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        INSERT INTO `user`
        (username,birthday,sex,address) VALUES
        (#{username},#{birthday},#{sex},#{address})
    </insert>

4.5.4.Mysql使用uuid实现主键

查询id的sql:

SELECT UUID()

<!-- 保存用户 -->
<insert id="saveUser2" parameterType="com.dayee.entity.User">
    <!-- selectKey 标签实现主键返回 -->
    <!-- keyColumn:主键对应的表中的哪一列 -->
    <!-- keyProperty:主键对应的pojo中的哪一个属性 -->
    <!-- order:设置在执行insert语句前执行查询id的sql,还是在执行insert语句之后执行查询id的sql -->
    <!-- resultType:设置返回的id的类型 -->
    <selectKey keyColumn="id" keyProperty="id" order="BEFORE" resultType="string">
        SELECT UUID()
    </selectKey>
    INSERT INTO `user`
    (username,birthday,sex,address) VALUES
    (#{username},#{birthday},#{sex},#{address})
</insert>

4.6.示例:修改用户

根据用户id修改用户名,使用的sql:

UPDATE `user` SET username = '赵云' WHERE id = 1

 

1.编辑UserMapper.xml映射文件

<!-- 更新用户 -->
<update id="updateUserById" parameterType="com.dayee.entity.User">
    UPDATE `user` SET
    username = #{username},
    sex = #{sex},
    birthday = #{birthday},
    address = #{address}
    WHERE id = #{id}
</update>

2.测试:MybatisTest.java

    @Test
    public void testUpdateUserById() {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行更新
        // 创建需要更新的User
        User user = new User();
        user.setId(1);
        user.setUsername("司马懿");
        user.setSex("1");
        user.setBirthday(new Date());
        user.setAddress("魏国");

        sqlSession.update("updateUserById", user);

        // 需要进行事务提交
        sqlSession.commit();

        // 7. 释放资源
        sqlSession.close();
    }

3.运行,数据库修改成功。

4.7.​​​示例:删除用户

根据用户id删除用户:
DELETE FROM `user` WHERE id = 4

1.编辑UserMapper.xml映射文件

<!-- 删除用户 -->
<delete id="deleteUserById" parameterType="int">
   delete from user where
   id=#{id}
</delete>

2.测试:MybatisTest.java

    @Test
    public void testDeleteUserById() {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行删除
        sqlSession.delete("deleteUserById", 4);

        // 需要进行事务提交
        sqlSession.commit();

        // 7. 释放资源
        sqlSession.close();
    }

3.运行,数据库删除成功。

5.JDBC,Mybatis,hibernate浅谈

5.1.Mybatis解决jdbc编程的问题

1)数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。

解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。

2)Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

3)向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。

4)对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

5.2.mybatis与hibernate的区别

Mybatis和hibernate不同,它不完全是一个ORM框架,因为MyBatis需要程序员自己编写Sql语句。mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。

Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。

Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。 

 

 

6.映射文件 Mapper.xml详解

6.1.<select>

id:是当前命名空间下的Statement的唯一标识(必须属性);要求id和mapper接口中的方法的名字一致。

parameterType:输入的参数类型(可以省略);

resultType:将结果集映射为java的对象类型。select表情中必须(和 resultMap 二选一),别的标签不用。

标签内部:编写SQL语句

 

6.2.<insert>

注意:传递的参数是User,可以直接通过 #{User实体类中的属性} 直接获取参数;

id:是当前命名空间下的Statement的唯一标识(必须属性);

parameterType:输入的参数类型(可以省略);

标签内部:编写SQL语句

 

6.3.<update>

id:是当前命名空间下的Statement的唯一标识(必须属性);

parameterType:输入的参数类型(可以省略);

标签内部:编写SQL语句

6.4.<delete>

id:是当前命名空间下的Statement的唯一标识(必须属性);

parameterType:输入的参数类型(可以省略);

标签内部:编写SQL语句

 

 

6.5.输入映射和输出映射

6.5.1.输入映射parameterType

parameterType可以传递简单类型,实体对象类型,以及实体对象包装类型。

1)传递简单类型

使用#{}占位符,或者${}进行sql拼接

2)实体对象类型

Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为实体属性名称

3)实体对象包装类型

也就是说Vo里面有实体类,根据实体类的属性操作数据

演示:

1.需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中

2.需要执行的Sql语句:

SELECT * FROM user WHERE username LIKE '%张%'

3.新增 QueryVo 类

public class QueryVo {

	// 包含实体对象
	private User user;

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
}

3.编辑UserMapper.xml文件

<select id="queryUserByQueryVo" parameterType="com.dayee.vo.QueryVo" resultType="com.dayee.entity.User">
    <!--以下user.id是包装类中的属性user字段的属性-->
	SELECT * FROM `user` WHERE username LIKE '%${user.username}%'
</select>

4.测试类:

    @Test
    public void queryUserByQueryVo() {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 5. 执行SqlSession对象执行查询,获取结果User
        QueryVo queryVo = new QueryVo();
        User user = new User();
        user.setUsername("张");
        queryVo.setUser(user);

        List<Object> list = sqlSession.selectList("queryUserByQueryVo", queryVo);

        // 6. 打印结果
        for (Object user2 : list) {
            System.out.println(user2);
        }

        // 7. 释放资源
        sqlSession.close();
    }

5.控制台

 

6.5.2.输出映射resultType

resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。

如果有多条数据,则分别进行映射,并把对象放到容器List中

resultType可以输出类型:简单类型,实体类型,实体类型列表

1)简单类型

注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。

2)实体类型和实体类型列表就不再演示了

     如果输出的是实体类型列表,mybatis会默认转成集合方式。

 

 

6.5.3.输出映射resultMap

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

 

1)创建user2表:

CREATE TABLE `user2` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(32) NOT NULL COMMENT '用户名称',
  `birth_day` date DEFAULT NULL COMMENT '生日',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `address` varchar(256) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8


insert into `user2` (`user_id`, `user_name`, `birth_day`, `sex`, `address`) values(1,'张飞','2002-08-01','男','北京');

 

2)UserMapper.xml配置文件

<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
    <!-- id:设置ResultMap的id -->
    <!-- autoMapping="true" 表示开启驼峰法,这个非必填-->
    <resultMap type="com.dayee.entity.User" id="userResultMap" autoMapping="true">
        <!-- 定义主键 ,非必写。如果是多个字段,则定义多个id -->
        <!-- property:主键在pojo中的属性名 -->
        <!-- column:主键在数据库中的列名 -->
        <id property="id" column="user_id" />
        <!-- 定义普通属性 -->
        <result property="username" column="user_name" />
        <result property="birthday" column="birth_day" />
        <result property="sex" column="sex" />
        <result property="address" column="address" />
    </resultMap>

    <!-- 查询所有的用户数据 -->
    <select id="queryUserAll" resultMap="userResultMap">
		SELECT * FROM `user2`
	</select>

说明:

  1. 如果没有在sqlmapconfig.xml中开启驼峰法,只设置autoMapping=“true”没有效果
  2. 主键id并不是必须指定的
  3. 如果属性名与字段名一致,则不写<result property="address" column="address" />也可以自动匹配到
  4. 如果开启了驼峰法,但实体属性名不符合驼峰法,运行程序会报错(驼峰法开启在后文有详解)

6.6.sql片段

外部的sql片段,除了指单独写的存储sql的片段的mapper,还有别的实体类的mapper文件。

6.7.动态sql

通过mybatis提供的各种标签方法实现动态拼接sql。

需求:根据性别和名字查询用户

查询sql:

SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%张%'

 <!-- 根据条件查询用户 -->
    <select id="queryUserByWhere1" parameterType="com.dayee.entity.User" resultType="com.dayee.entity.User">
        SELECT id, username, birthday, sex, address FROM `user`
        WHERE sex = #{sex} AND username LIKE
        '%${username}%'
    </select>
    

上面这种写法,如果sex或者username的值有一个是空的话,就查不到数据,如果我想达到有值就带上此参数,没有值就不带此参数的效果的话,我们就需要换一种写法了。

6.7.1.If标签

 <!-- 根据条件查询用户 -->
    <select id="queryUserByWhere2" parameterType="com.dayee.entity.User" resultType="com.dayee.entity.User">
        SELECT id, username, birthday, sex, address FROM `user`
        WHERE 1=1
        <if test="sex != null and sex != ''">
            AND sex = #{sex}
        </if>
        <if test="username != null and username != ''">
            AND username LIKE
            '%${username}%'
        </if>
    </select>

注:字符串类型的数据需要要做不等于空字符串校验。

 

6.7.2.choose, when, otherwise标签

 

6.7.3.Where,set标签

上面的sql还有where 1=1 这样的语句,很麻烦,可以使用where标签进行改造

<!-- 根据条件查询用户 -->
    <select id="queryUserByWhere3" parameterType="com.dayee.entity.User" resultType="com.dayee.entity.User">
        SELECT id, username, birthday, sex, address FROM `user`
        <!-- where标签可以自动添加where,同时处理sql语句中第一个and关键字 -->
        <where>
            <if test="sex != null">
                AND sex = #{sex}
            </if>
            <if test="username != null and username != ''">
                AND username LIKE
                '%${username}%'
            </if>
        </where>
    </select>

取代WHERE和SET关键字,并且处理SQL语句的中语法错误

<where>标签可以处理每个if中的前面的and问题,不会使sql语句出错,但不会处理后面的and问题

<set> 标签可自动处理每个拼接片段后的 逗号,但不处理前面的 逗号。

6.7.4.foreach标签

向sql传递数组或List,mybatis使用foreach解析,如下:

根据多个id查询用户信息,查询sql:

SELECT * FROM user WHERE id IN (1,10,24)

1.QueryVo

package com.dayee.vo;

import java.util.List;

public class QueryVo {

	private List<Integer> ids;

	public List<Integer> getIds() {
		return ids;
	}

	public void setIds(List<Integer> ids) {
		this.ids = ids;
	}
}

2.UserMapper.xml

<!-- 根据ids查询用户 -->
    <select id="queryUserByIds" parameterType="com.dayee.vo.QueryVo" resultType="com.dayee.entity.User">
        SELECT * FROM `user`
        <where>
            <!-- foreach标签,进行遍历 -->
            <!-- collection:遍历的集合,这里是QueryVo的ids属性 -->
            <!-- item:遍历的项目,可以随便写,,但是和后面的#{}里面要一致 -->
            <!-- open:在前面添加的sql片段 -->
            <!-- close:在结尾处添加的sql片段 -->
            <!-- separator:指定遍历的元素之间使用的分隔符 -->
            <foreach collection="ids" item="item" open="id IN (" close=")" separator=",">
                #{item}
            </foreach>
        </where>
    </select>

3.测试类

@Test
    public void queryUserByIds() {
        // 4. 创建SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        QueryVo queryVo = new QueryVo();
        List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(24);
        queryVo.setIds(ids);
        List<Object> list = sqlSession.selectList("queryUserByIds", queryVo);

        // 6. 打印结果
        for (Object user2 : list) {
            System.out.println(user2);
        }

        // 7. 释放资源
        sqlSession.close();
    }

4.控制台

7.SqlMapConfig.xml配置文件详解

SqlMapConfig.xml讲究严格的顺序,具体顺序遵循文档的顺序

 

7.1.properties属性读取外部资源配置文件

 

7.2.settings(设置)

7.3.​​​​​​​typeAliases(别名)

7.4.​​​​​​​typeHandlers(类型处理器)

7.5.​​​​​​​plugins(插件,又名拦截器)

7.6.​​​​​​​environments(环境)

7.7.Mapper

8.缓存(了解)

​​​​​​​8.1.一级缓存

在Mybatis中一级缓存是默认开启,并且无法关闭。

测试一级缓存:

一级缓存满足条件:

  1. 同一个session中
  2. 相同的SQL和参数

 

使用session.clearCache()强制查询不缓存。

在执行insert、update、delete时会刷新缓存。

 

​​​​​​​8.2.二级缓存

开启二级缓存:

注意:在Mybatis-Config中有缓存的全局控制器(cacheEnabled),默认是开启的,所以无需手动开启。

 

关闭二级缓存:

 

​​​​​​​更多参数

​​​​​​​8.3.使用第三方缓存实现二级缓存

Memcache:是一个高性能的KV缓存框架(服务),在之前非常的火,目前逐步被Redis所替代。

 

 

9.延迟加载(了解)

​​​​​​​9.1.cglib支持

​​​​​​​9.2.编写接口

​​​​​​​9.3.编写Mapper.xml

​​​​​​​9.4.测试

结果:

 

10.分页插件

10.1.实现通用分页组件

 10.2.Mybatisplugin实现原理

10.3.使用PageHelper实现分页

​​​​​​​10.3.1.导入依赖

10.3.2.配置插件

10.3.3.在执行查询时设置分页参数

猜你喜欢

转载自blog.csdn.net/xuruanshun/article/details/102684879