Mybatis概述

MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使 开发者只需要关注SQL本身,而不需要花费精力去处理例如注册驱动、创建 connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。

Mybatis通过xml注解的方式将要执行的各种statement(statement、 preparedStatemnt)配置起来,并通过java对象和statement中的sql进行映射生成 终执行的sql语句,后由mybatis框架执行sql并将结果映射成java对象并返回。

总之,Mybatis对JDBC访问数据库的过程进行了封装,简化了JDBC代码,解决 JDBC将结果集封装为Java对象的麻烦.

下图是MyBatis架构图:
image.png
(1)mybatis-config.xml是Mybatis的核心配置文件,通过其中的配置可以生成 SqlSessionFactory,也就是SqlSession工厂
(2)基于SqlSessionFactory可以生成SqlSession对象
(3)SqlSession是一个既可以发送SQL去执行,并返回结果,类似于JDBC中的 Connection对象,也是Mybatis中至关重要的一个对象。
(4)Executor是SqlSession底层的对象,用于执行SQL语句
(5)MapperStatement对象也是SqlSession底层的对象,用于接收输入映射(SQL 语句中的参数),以及做输出映射(即将SQL查询的结果映射成相应的结果)

Mybatis实现

逆向工程

通过逆向工程生成sql语句。
image.png
第一步:导入generator原始文件,并修改generatorConfig.xml配置文件
image.png

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="testTables" targetRuntime="MyBatis3">

        <!-- JavaBean 实现 序列化 接口 -->
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin">
        </plugin>
        <!-- genenat entity时,生成toString -->
        <plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
<!-- 共用5处要修改 -->

        <!--修改1: 数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/mall" userId="root"
            password="root">
        </jdbcConnection>

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 
            和 NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!--修改2:  targetProject:生成PO类的位置 -->
        <javaModelGenerator targetPackage="com.tedu.jtmall.pojo"
            targetProject=".\src\main\java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--修改3:  targetProject:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="com.tedu.jtmall.mapper"
            targetProject=".\src\main\java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        
        <!-- 修改4: targetPackage:mapper接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
            targetPackage="com.tedu.jtmall.mapper" targetProject=".\src\main\java">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!--修改5:  指定数据库表 -->        
        <table tableName="category" />
        <table tableName="item" />
<table tableName="user" />
        <table tableName="jt_order" />
<table tableName="admin" />
        
        
    </context>
</generatorConfiguration>

第二步:执行GeneratorApp生成xml和实体类
image.png
执行GeneratorApp后,选中项目右键refresh,查看生成的xml和类如下图:
image.png

实现CRUD操作

第一步:复制逆向工程生成的Mapper接口和xml文件以及pojo实体类
image.png
第二步:主程序上添加包扫描@MapperScan("...")

package com.tedu.mybatis02_multiTable;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//框架为com.tedu.jtmall.mapper包下的接口自动创建代理对象
@MapperScan("com.tedu.mybatis02_multiTable.mapper")
public class Mybatis02MultiTableApplication {

    public static void main(String[] args) {
        SpringApplication.run(Mybatis02MultiTableApplication.class, args);
    }

}

第三步:配置yml文件

server:
  port: 8080

spring:     
    datasource:        
        driver-class-name: com.mysql.cj.jdbc.Driver        
        url: jdbc:mysql://localhost:3306/mall?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2b8
        username: root        
        password: root
    
mybatis:
  mapperLocations: classpath:com.tedu.jtmall.mapper/*.xml

logging:
  path: ./logs
  level: 
    com.tedu.jtmall.mapper: debug

第四步:创建控制层CategoryController类,完成查询操作
1.创建CategoryController类

package com.tedu.mybatis02_multiTable.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.tedu.mybatis02_multiTable.mapper.CategoryMapper;
import com.tedu.mybatis02_multiTable.pojo.Category;

@RestController
public class CategoryController {
    @Autowired
    CategoryMapper categoryMapper;
    
    @RequestMapping("/cat")
    public Category cat() {
        return categoryMapper.selectCategory(1);
    }
}

2.编辑查看xml文件

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace的值是接口所在的包名+接口名 -->
<mapper
    namespace="com.tedu.mybatis02_multiTable.mapper.CategoryMapper">
    <!-- 1,映射:结果集和类的映射 type:商品分类类名 id:自命名 -->
    <resultMap type="com.tedu.mybatis02_multiTable.pojo.Category"
        id="categoryMap">
        <result column="category_id" property="categoryId" />
        <result column="category_name" property="categoryName" />
        <!-- 一个分类下有多个商品 ofType:商品的类名 -->
        <collection property="itemList"
            ofType="com.tedu.mybatis02_multiTable.pojo.Item">
            <result column="item_name" property="itemName"/>
        </collection>
    </resultMap>
    <!-- 2,sql语句 
    id必须和方法名一致-->
    <select id="selectCategory" resultMap="categoryMap" parameterType="Integer">
        SELECT category.category_id,category_name,item_name
        FROM category,item
        WHERE category.category_id=#{categoryId}
        AND item.category_id=category.category_id
    </select>

</ma

MybatisPlus+Lombok

利用MP可,可有spring自动生成xml文件,切接口中底层已自定义基本的CRUD方法,可省略。
Lombok可在pojo类上添加注解,自动生成get、set、构造函数等方法。
image.png

第一步:添加Lombok、MP核心库、springboot整合mp的依赖

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.tedu</groupId>
    <artifactId>mybatis04_plus</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis04_plus</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
    <!-- lombok -->
    <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>    
    
        <!-- mybatisplus与springboot整合 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatisplus-spring-boot-starter</artifactId>
            <version>1.0.5</version>
        </dependency>
        <!-- MP 核心库 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>2.3</version>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.3</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

第二步:pojo类上添加@Data注解,自动生成get、set方法

package com.tedu.mybatis04_plus.pojo;

import lombok.Data;

@Data//lombok会为User生成set,get
//从网上下载代码,如果发现实体类没有set(),get(),加了@data,
//说明项目用了lombok
public class User {
    Integer userId;
}

第三步:pojo类上添加注解实现MP

package com.tedu.mybatis04_plus.pojo;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import lombok.Data;

//对应catepory表
//实现映射,以前是在CategoryMapper.xml中实现
@Data
@TableName("category")
public class Category {
    //映射到category_id列
    //以前是在xml中写rsult column=category_id property=categoryId
    @TableField("category_id")
    Integer categoryId;
    
    @TableField("category_name")
    String categoryName;
}

第四步:创建接口CategoryMapper继承BaseMapper<pojo>

package com.tedu.mybatis04_plus.mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.tedu.mybatis04_plus.pojo.Category;

//以前为们要写insert(),delete(),update(),select()
//BaseMapper中有insert(),delete(),update(),select()
public interface CategoryMapper extends BaseMapper<Category>{

}

第五步:创建CategoryController类

package com.tedu.mybatis04_plus.controller;

import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.tedu.mybatis04_plus.mapper.CategoryMapper;
import com.tedu.mybatis04_plus.pojo.Category;

@RestController
public class CategoryController {
    @Autowired
    CategoryMapper categoryMapper;
    
    @RequestMapping("/select")
    public List<Category> select(){
        //设置排序
        EntityWrapper<Category> wrapper=new EntityWrapper();
        wrapper.orderBy("category_id desc");
        //调用baseMapper中的selectList()
        return categoryMapper.selectList(wrapper);
    }
}

第六步:创建启动类Mybatis04PlusApplication

package com.tedu.mybatis04_plus;

import java.lang.reflect.Method;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.tedu.mybatis04_plus.pojo.User;

@MapperScan("com.tedu.mybatis04_plus.mapper")
@SpringBootApplication
public class Mybatis04PlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(Mybatis04PlusApplication.class, args);
    
    //测试User类有没有set(),get()
        User user=new User();
        user.setUserId(6688);
        System.out.println(user.getUserId());
        Class clazz=User.class;
        Method[] methods=clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        
        }
    
    }

}

动态sql

<if> 标签:是根据 test属性 中的布尔表达式的值,从而决定是否执行包 含在其中的SQL片段。如果判断结果为true,则执行其中的SQL片段;如果 结果为false,则不执行其中的SQL片段

<where> 标签:用于对包含在其中的SQL片段进行检索,在需要时可以生 成where关键字,并且在需要时会剔除多余的连接词(比如and或者or)

foreach 标签:可以对传过来的参数数组或集合进行遍历,以下是foreach标签 上的各个属性介绍
image.png

第一步:创建springboot项目mybatis03_dynamicSql
image.png
第二步:创建Item实体类

package com.tedu.mybatis03_dynamicsql.pojo;
//对应item表
@Data
public class Item {
    Integer itemId;
    String itemName;
    

第三步:创建Mapper接口

package com.tedu.mybatis03_dynamicsql.mapper;
//操作Item表的

import java.util.List;

import com.tedu.mybatis03_dynamicsql.pojo.Item;

public interface ItemMapper {
    //如果返回的是多个数据,加个list
    public List<Item> select(Item item);
    //查询多个商品
    public List<Item> list(List<Integer> idList);
}

第四步:启动类上添加包扫描@MapperScan("...")

@SpringBootApplication
@MapperScan("com.tedu.dynamicSql.mapper")
public class DynamicSqlApplication {

    public static void main(String[] args) {
        SpringApplication.run(DynamicSqlApplication.class, args);
    }
}

第五步:创建控制层ItemController

package com.tedu.mybatis03_dynamicsql.controller;


import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tedu.mybatis03_dynamicsql.mapper.ItemMapper;
import com.tedu.mybatis03_dynamicsql.pojo.Item;

@RestController
public class ItemController {
    //从spring ioc的容器中获取代理对象
    @Autowired
    ItemMapper  itemMapper;
    
    @RequestMapping("/item")
    public List<Item> select(Item item){
        
        return itemMapper.select(item);
    }
    @RequestMapping("/list")
    public List<Item> list(){
        ArrayList<Integer> idList=new ArrayList<Integer>();
        idList.add(2);
        idList.add(3);
        return itemMapper.list(idList);
    }
}

第六步:创建xml文件

<!-- copy9.4.6 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口的全名称 -->
<mapper
    namespace="com.tedu.mybatis03_dynamicsql.mapper.ItemMapper">
    <!-- id必须和接口中的方法名一致 -->
    <!-- mybatis矿建判断结果集如果是多行,自动创建list -->
    <select id="select"
        parameterType="com.tedu.mybatis03_dynamicsql.pojo.Item"
        resultType="com.tedu.mybatis03_dynamicsql.pojo.Item">
        SELECT item_id AS itemId,
        item_name AS itemName
        FROM item
        <!-- 用户可以根据分类的id,商品id,商品名称,商品价格 Item中包含的是查询条件 判断item中有没有商品id,如果有加上item_id=1 
            判断item中有没有商品名称,如果有加上and item_name like '%itemName%' -->
        <where>
            <if test="itemId !=null">
                item_id=#{itemId}
            </if>
            <!-- concat是mysql函数,实现字符串相加,每个字符串中间用,分隔空开 -->
            <if test="itemName !=null">
                and item_name like concat('%',#{itemName},'%')
            </if>
        </where>
    </select>
    <!-- id必须和方法名一样 -->
    <select id="list"
        parameterType="Integer"
        resultType="com.tedu.mybatis03_dynamicsql.pojo.Item">
        SELECT item_id AS itemId,
        item_name AS itemName
        FROM item
        <where>
            <!-- 遍历idList集合,取出来的数据叫id (2,3) -->
            item_id in
            <foreach collection="idList" item="id" open="(" separator=","
                close=")">
                #{id}
            </foreach>
        </where>

    </select>

</mapper>

占位符#{}和${}的区别

1.#{}相当于JDBC中的问号(?)占位符,是为SQL语句中的参数值进行占位,大部分情况下都是使用#{}占位符;并且当#{}占位符是为字符串或者日期类型的值进行占位时,在参数值传过来替换占位符的同时,会进行转义处理(在字符串或日期类型的值的两边加上单引号);
2.${}是为SQL片段(字符串)进行占位,将传过来的SQL片段直接拼接在占位符所在的位置,不会进行任何的转义处理.(由于是直接将参数拼接在SQL语句中,因此可能会引发SQL注入攻击问题)

在mapper文件中: select * from emp where name=#{name} 
在程序执行时: select * from emp where name=? 
参数:王海涛,将参数传入,替换占位符 
select * from emp where name=王海涛; -- 错误 
select * from emp where name=‘王海涛’; -- 正确 

需要注意的是:使用 ${} 占位符为SQL语句中的片段占位时,即使只有一个占位符,需要传的也只有一个参数,也需要将参数先封装再传递!


木安
13 声望6 粉丝

« 上一篇
SSM-Spring
下一篇 »
SpringBoot介绍