当前位置:   article > 正文

Mybatis框架

mybatis框架

1. Mybatis 介绍

  Mybatis: 优秀的持久层框架,用于简化JDBC的开发.支持自定义 SQL, 存储过程和高级映射。几乎消除了 所有 JDBC 代码和手动设置参数和检索的结果。MyBatis 可以使用简单的 XML 或 的注释配置和映射文件和映射接口和数据映射(普通 Java 对象)到数据库记录。
  Mybatis是对JDBC代码的封装与简化
在这里插入图片描述

 Mybatis官网:Mybatis官网

在这里插入图片描述

2. Mybatis 依赖

 A. Mybatis依赖(Maven)

<!--mysql驱动连接 jar包-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.31</version>
</dependency>
<!--Mybatis框架 jar包-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.5</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 B. 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.cj.jdbc.Driver"/>
                <!--数据库连接名 : xxxxxx-->
                <property name="url" value="jdbc:mysql:///xxxxxx?useSSL=false&amp;useServerPrepStmts=true"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <!--扫描mapper xxx.xxx-->
    <mappers>
        <package name="xxx.xxx"/>
    </mappers>

</configuration>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

3. Mybatis 入门

3.1 Mapper 代理开发

在这里插入图片描述

3.2 Mapper 映射文件(一定要与映射接口同名)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--Mapper接口全限定名-->
<mapper namespace="com.dao.xxx">
    <!--id 与接口方法名对应, 保持参数和返回类型一致-->
    <select id="xxxxx" resultType="com.pojo.xxxx">
        SQL语句
    </select>
</mapper>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.3 Mapper 映射接口

package com.dao;
import com.pojo.User;
public interface UserMapper {
	User selectById(int id);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

3.4 Sqlsession 获取代理对象执行SQL

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userMapper.xxxx()

sqlSession.close(); // 释放资源
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

4. log4j日志

 A. 相关依赖配置(Maven)

<!--junit测试单元 jar包-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13</version>
</dependency>
<!--log4j配置 jar包-->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

 B. log4j.properties

log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

 c. mybatis-config.xml当中加入log4j的相关设置

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
  • 1
  • 2
  • 3

5. Mybatis 配置(mybatis-config.xml)

Mybatis 配置文件严格按照顺序配置元素

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--配置相关属性文件-->
    <properties></properties>
    <!--setting项, 对Mybatis运行行为调整-->
    <settings></settings>
	<!--简化合格的类名-->
    <typeAliases></typeAliases>
	<!--解决自定义数据类型与JDBC数据库类型转换-->
    <typeHandlers></typeHandlers>
	<!--创建新的结果集对象-->
    <objectFactory></objectFactory>
	<!--配置plugins拦截器-->
    <plugins></plugins>
	<!--数据源环境配置-->
    <environments default="">
        <environment id="">
            <transactionManager type=""></transactionManager>
            <dataSource type=""></dataSource>
        </environment>
    </environments>
	<!--配置xml映射文件路径-->
    <mappers></mappers>
</configuration>

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

5.1 properties 文件

A. properties文件 : 支持读取外部的属性文件,这样可以在属性文件中配置大量备用信息,而Mybatis可以根据键值选择使用部分内容.
B. db.properties文件

driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/test?useSSL=false&useServerPrepStmts=true
username = root
password = 123456
  • 1
  • 2
  • 3
  • 4

C. Mybatis配置文件当中进行声明

<properties resource="db.properties"></properties>

<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

6. 动态SQL

6.1 Dynamic SQL 介绍

  动态SQL语句是用来简化用户在有条件时拼接SQL语句的操作,当有条件的拼接SQL语句的时候我们就可以使用动态SQL来简化SQL语句的编写
在这里插入图片描述


  以下示例用户表结构
在这里插入图片描述

6.2 数据查询

  a. 动态单条件查询:
在这里插入图片描述
代码及运行结果 : 会根据条件的不同, 自动组装出不同的SQL语句

<select id="selectUser" resultType="com.pojo.User">
    select * from tb_user where
    <choose>
        <when test="id != null">
            id = #{id}
        </when>
        <when test="username != null">
            username = #{username}
        </when>
        <when test="password != null">
            password = #{password}
        </when>
        <otherwise>
            1 = 1
        </otherwise>
    </choose>
</select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
public static void main(String[] args) throws IOException {
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession sqlSession = sqlSessionFactory.openSession();
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

	List<User> list = userMapper.selectUser(1, "1", null); // 默认匹配第一个成功匹配的条件
	/*   若都不匹配则执行最后的otherwise语句
	List<User> list = userMapper.selectUser(null, null, null); */
	
	System.out.println(list);
	sqlSession.close(); // 释放资源
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

  ## 匹配第一个成功匹配的语句
在这里插入图片描述
  ## 执行otherwise语句
在这里插入图片描述

  b. 动态多条件查询:
  使用where标签去完成动态多条件查询,此标签会动态判断当语句以 and/or 开头时,会动态将其删除,将其改为一个合法的SQL语句
在这里插入图片描述

    <select id="selectUser" resultType="com.pojo.User">
        select * from tb_user
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
            <if test="username != null">
                and username = #{username}
            </if>
            <if test="password != null">
                and password = #{password}
            </if>
        </where>
    </select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
	public static void main(String[] args) throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

		List<User> list = userMapper.selectUser(null, "1", "123");
		System.out.println(list);

		sqlSession.close(); // 释放资源
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

  ## 自动处理多余的 and / or 连接字符

6.3 数据添加

  注意Mybatis 事务默认是开启的,对数据表进行修改操作需要手动提交事务(或者在开始设置时就将其设置为自动添加)
  Mybatis 可以设置主键自增,让数据库自己自动生成主键,并且通过keyProperty可以映射回生成的主键
在这里插入图片描述
在这里插入图片描述

<insert id="insetUser" useGeneratedKeys="true" keyProperty="id">
    insert into tb_user(id, username, password) values(#{id}, #{username}, #{password});
</insert>
  • 1
  • 2
  • 3
	public static void main(String[] args) throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

		User u = new User(0, "7", "7");
		userMapper.insetUser(u);
		System.out.println(u); // 注意关注User的id, 会被返回成自动生成的主键

		sqlSession.commit(); // 事务提交
		sqlSession.close(); // 释放资源
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

  ## 自动生成主键,并将主键返回到对象当中
在这里插入图片描述

6.4 数据修改

  通过使用 set标签 + if 语句 进行动态的修改部分数据。 set标签会动态判断合法的内容,然后动态的将多余的逗号删除

<update id="updateUser">
    update tb_user
    <set>
        <if test="username != null and username != '' ">
            username = #{username},
        </if>
        <if test="password != null and password != '' ">
            password = #{password},
        </if>
    </set>
    where id = #{id}
</update>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
	public static void main(String[] args) throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		SqlSession sqlSession = sqlSessionFactory.openSession();
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

		User u = new User(1, "11", "12");
		userMapper.updateUser(u);

		sqlSession.commit(); // 事务提交
		sqlSession.close(); // 释放资源
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  ## 自动对合法修改内容进行拼接(删除末尾多余的逗号)
在这里插入图片描述

6.5 数据删除

  借助foreach语句可以实现批量删除
在这里插入图片描述

<delete id="deleteUser">
    delete from tb_user where id in
    <!-- 从collection当中取出元素集合, item: 每个元素的名字, seperator: 元素之间的分隔符, open/clos: 语句起始结尾符号 -->
    <foreach collection="ids" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
public static void main(String[] args) throws IOException {
	String resource = "mybatis-config.xml";
	InputStream inputStream = Resources.getResourceAsStream(resource);
	SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
	SqlSession sqlSession = sqlSessionFactory.openSession();
	UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

	int id[] = {1, 2};
	userMapper.deleteUser(id);

	sqlSession.commit(); // 事务提交
	sqlSession.close(); // 释放资源
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  ## 运行结果
在这里插入图片描述

7. 占位符,特殊字符

7.1 占位符

#{}: 会使用 ? 代替原位置占位符, 之后再自动设置参数 (参数传递时使用)
${}: 会直接拼接SQL语句,可能会造成SQL注入问题. (可以用于对表名与列名进行动态设置)
  • 1
  • 2

  #{}占位符使用
在这里插入图片描述

  ${}占位符使用
在这里插入图片描述

7.2 特殊字符处理

1. 使用转义字符处理
2. 使用 <![CDATA[内容]]> 处理
  • 1
  • 2
<select id="selectUserById" resultType="com.pojo.User">
    select * from tb_user where id
    <!--或者使用转义字符 &lt; -->
    <![CDATA[
        <
    ]]>
    #{id}
</select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  ## 运行结果
在这里插入图片描述

8. 参数传递原理

8.1 参数封装底层代码

    public Object getNamedParams(Object[] args) { // 处理参数封装
        int paramCount = this.names.size();
        if (args != null && paramCount != 0) {
            if (!this.hasParamAnnotation && paramCount == 1) { // 单个参数 且 未使用注解
                Object value = args[(Integer)this.names.firstKey()];
                // 调用方法进行封装
                return wrapToMapIfCollection(value, this.useActualParamName ? (String)this.names.get(0) : null);
            } else { // 多个参数或者使用了注解
                Map<String, Object> param = new ParamMap();
                int i = 0;

                for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {
                    Entry<Integer, String> entry = (Entry)var5.next();
                    param.put(entry.getValue(), args[(Integer)entry.getKey()]); // 产生 arg[] 或者 注解 键
                    String genericParamName = "param" + (i + 1);
                    if (!this.names.containsValue(genericParamName)) { // 产生 param键(不与其他键发生冲突前提下)
                        param.put(genericParamName, args[(Integer)entry.getKey()]);
                    }
                }

                return param;
            }
        } else {
            return null;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
 public static Object wrapToMapIfCollection(Object object, String actualParamName) { // 用于封装单个参数
        ParamMap map;
        if (object instanceof Collection) {
            map = new ParamMap();
            map.put("collection", object);
            if (object instanceof List) {
                map.put("list", object);
            }

            Optional.ofNullable(actualParamName).ifPresent((name) -> {
                map.put(name, object);
            });
            return map;
        } else if (object != null && object.getClass().isArray()) {
            map = new ParamMap();
            map.put("array", object);
            Optional.ofNullable(actualParamName).ifPresent((name) -> {
                map.put(name, object);
            });
            return map;
        } else {
            return object;
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述

8.2 单个参数封装(未使用注解)

 底层代码分析
在这里插入图片描述

  单个参数封装:
在这里插入图片描述

8.2 多个参数封装 / 单个参数使用注解

 底层代码分析
在这里插入图片描述

  多个参数封装:
在这里插入图片描述

8.4 具体代码实现运用

a. Pojo: 属性名调用
Pojo: 直接使用属性名字进行调用
  • 1

在这里插入图片描述

b. Map: 键名调用
Map集合: 键名与参数占位符一致
  • 1

在这里插入图片描述

c. Collection / list : foreach循环调用
Collection / list : 使用foreach循环

collection: 集合名称, item: 遍历的每个集合元素名称, index: 该元素的下标
seperator: 元素之间的分隔符, open/clos: 语句起始结尾符号
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

d. Array: 数组下标 / foreach循环
数组下标: array[0] / array[1]
  • 1

在这里插入图片描述

e. 其他:直接使用
其他:直接使用就行,参数名字是无所谓的,可以任意取参数名
  • 1

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/922014
推荐阅读
相关标签
  

闽ICP备14008679号