Mybatis

Mybatis

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。

MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

入门

导入依赖

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

创建mapper接口

@Mapper
public interface EmployeeMapper {
    Employee getEmpById(Integer id);
}

创建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" >
<!--
 namespace : mapper接口的全类名
-->
<mapper namespace="com.chs.mapper.EmployeeMapper">
    <!--
	id: mapper接口的方法名
	resultType: 返回值类型的全类名
	-->
    <select id="getEmpById" resultType="com.chs.bean.Employee">
         select id,emp_name empName,age,emp_salary empSalary from t_emp where id = #{id}
    </select>
</mapper>

配置application.properties文件:说明mapper.xml文件的位置

mybatis.mapper-locations=classpath:mapper/**.xml  #扫描resourcex/mapper下的全部.xml文件

mybatis.configuration.map-underscore-to-camel-case=true  #开启驼峰映射为下划线格式  ==> empName == emp_name

logging.level.com.chs.mapper.**=debug  #控制台打印mybatis的sql语句

MyBatis 设置自动回填id字段

useGeneratedKeys:jdbc规范中提供了此设置,mybatis对此也进行了实现

keyProperty:指定主键的属性名

<insert id="insertEmployee" useGeneratedKeys="true" keyProperty="empId">
  insert into t_emp(emp_name,emp_salary)
  values(#{empName},#{empSalary})
</insert>

MyBatis 参数传递

#{}:底层使用 PreparedStatement 方式,SQL预编译后设置参数,无SQL注入攻击风险

${}:底层使用 Statement 方式,SQL无预编译,直接拼接参数,有SQL注入攻击风险

使用时机:

参数传递,都使用 #{}

如果要对表名、列名进行动态设置,只能使用 ${} 进行 sql 拼接。

参数取值

传参形式 示例 取值方式
单个参数 - 普通类型 getEmploy(Long id) #
单个参数 - List类型 getEmploy(List id) #
单个参数 - 对象类型 addEmploy(Employee e) #
单个参数 - Map类型 addEmploy(Map<String,Object> m) #
多个参数 - 无@Param getEmploy(Long id,String name) #{变量名} //新版兼容
import org.apache.ibatis.annotations.Param;  

public interface UserMapper {  
    //   
    User addEmp(Employee emp);  
}

//对应的 XML 映射器
<insert id="addEmp">												//直接使用
   insert into t_emp(emp_name,age,emp_salary) values (#{empName},#{age},#{empSalary})
</insert>

@Param

在 MyBatis 中,@Param 注解用于指定映射器方法中的参数名称。这在方法有多个参数时特别有用,可以在 SQL 查询中引用这些参数。

@Param 的用法概述

  • 目的:将方法参数绑定到 SQL 查询参数。
  • 使用:允许为参数命名,以便在 SQL 语句中引用。
@Mapper
public interface UserMapper {  
    // 根据用户 ID 和名称查找用户  
    User findUserByIdAndName(@Param("userId") int id, @Param("userName") String name);  
}

//对应的 XML 映射器
<select id="findUserByIdAndName" parameterType="map" resultType="User">  
    SELECT * FROM users  
    WHERE id = #{userId} AND name = #{userName}  
</select>


@Mapper
public interface EmployeeMapper {
    void addEmp(@Param("emp") Employee employee);
}
    
<insert id="addEmp">
        insert into t_emp(emp_name,age,emp_salary) values (#{emp.empName},#{emp.age},#{emp.empSalary})
</insert>
多个参数 - 有@Param getEmploy(@Param(“id”)Long id,@Param(“name”)String name) #
扩展: getEmploy(@Param(“ext”)Map<String,Object> m,
@Param(“ids”)List ids,
@Param(“emp”)Employ e)
#{ext.age},
#{ids[0]}、
#{emp.age}

MyBatis 结果封装

返回普通数据

返回基本类型、普通对象 都只需要在 resultType 中声明返回值类型全类名即可

<select id="countEmp" resultType="java.lang.Long">
    select count(*) from  t_emp
</select>
   
<select id="getEmp" resultType="com.atguigu.mybatis.entity.Employee">
    select * from t_emp where id = #{id}
</select>

对象封装建议全局开启驼峰命名规则:mapUnderscoreToCamelCase = true;

返回List、Map

List:resultType 为集合中的 元素类型

<select id="getAll" resultType="com.chs.bean.Employee">
        select * from t_emp;
</select>

Map:resultType 为 map中的 元素类型,配合 @MapKey 指定哪一列的值作为Map 的 key,Map 的 Value 为这一行数据的完整信息

//mapper接口
@MapKey("id")
Map<Integer, Emp> getAllMap();
// 实际保存的不是 Employee,是 HashMap 需要自己封装成Employee

//xml文件
<select id="getAll" resultType="com.chs.bean.Employee">
        select * from t_emp;
</select>

自定义结果集 - ResultMap

数据库的字段 如果和 Bean的属性 不能一一对应时

如果符合驼峰命名,则开启驼峰命名规则就可以自动映射

自定映射规则:
1.如果在resultMap中映射主表对象时名称相同时可以省略不写。

2.当映射从表对象时(一对一/一对多)需要都配置手动映射否则所有的映射都失效。

3.autoMapping="true”==》只对当前对象有效。

autoMapping 设置为 true 时,框架会自动根据对象属性和数据库表字段之间的名称匹配来进行映射。

4.mybatis有全局配置的autoMapping:="true”局部可以省略不写
auto-mapping-behavior:full

注意autoMapping

  • 确保数据库表字段与对象属性的名称格式一致,以避免映射错误。
  • 避免重名:主映射与子映射不能有重名字段,如果有需要自己手动配映射。

编写自定义结果集(ResultMap) 进行封装

<!--自定义结果集-->
<resultMap id="EmpResultMap" type="com.atguigu.mybatis.entity.Employee">
    <!-- 

	column:为数据库的字段名
	property:为javaBean的属性名

	-->
    <id column="emp_id" property="empId"/>
    <result column="emp_name" property="empName"/>
    <result column="emp_salary" property="empSalary"/>
</resultMap>

<!--使用自定义结果集:resulMap-->
<select id="getCustomerByIdWithOrders" resultMap="EmpResultMap">
    <!--SQL语句-->
</select>

id 标签:必须指定主键列映射规则

result 标签:指定普通列映射规则

collection 标签

在 MyBatis 中,<collection> 标签用于映射数据库中一对多的关系。它可以将一个父对象中的集合属性与子对象的数据进行映射,从而在查询时能够获取到相关的多条数据。

标签中参数

ofType:指定集合中每个元素的类型

select:指定分步查询调用的方法

column:指定分步查询传递的参数列

public class User {  
    private int id;  
    private String name;  
    private List<Order> orders; // 一对多关系  

    // getters and setters  
}  

public class Order {  
    private int id;  
    private String address;  
    private int userId;  

    // getters and setters  
}

MyBatis映射文件

<resultMap id="ResultMap" type="com.chs.mybatis.bean.User">
        <id column="u_id" property="id"></id>
        <result column="name" property="name"></result>
<!--
collection:说明 一对N 的封装规则
ofType: 集合中元素的类型
-->
        <collection property="orders" ofType="com.atguigu.chs.bean.Order">
            <id column="id" property="id"></id>
            <result column="address" property="address"></result>
            <result column="u_id" property="userId"></result>
        </collection>
</resultMap>

 <!--使用自定义结果集-->
<select id="selectUserWithOrderById" resultMap="ResultMap">  
     <!--SQL语句-->
</select>  

resultMap 定义了映射关系,<collection> 标签用于定义 User 对象中的 orders 属性。

property 属性指定要填充的对象属性ofType 指定集合中对象的类型

association 标签

在 MyBatis 中,<association> 标签用于映射数据库中的一对一关系。它可以将父对象的属性映射到与之相关的单个子对象。

标签中参数

javaType:指定关联的Bean的类型

select:指定分步查询调用的方法

column:指定分步查询传递的参数列

public class User {  
    private int id;  
    private String name;  
    private Profile profile; // 一对一关系  

    // getters and setters  
}  

public class Profile {  
    private int id;  
    private String bio;  
    private int userId;  

    // getters and setters  
}

MyBatis 映射文件:

<resultMap id="OrderRM" type="com.chs.mybatis.bean.User">
    <id column="id" property="id"></id>
     <result column="name" property="name"></result>
        <!--  一对一关联封装  -->
     <association property="profile" javaType="com.chs.mybatis.bean.Profile">
         <id column="p_id" property="id"></id>
         <result column="bio" property="bio"></result>
         <result column="user_id" property="userId"></result>
     </association>
</resultMap>
 
<!--使用自定义结果集-->
<select id="selectUserWithProfileById" resultMap="OrderRM">  
    <!--SQL语句-->
</select>  

resultMap 定义了映射关系,<association> 标签用于定义 User 对象中的 profile 属性。

property 属性指定要填充的对象属性javaType 指定相关对象的类型。

分步查询

在 association 和 collection 的封装过程中,可以使用 select + column 指定分步查询逻辑

select:指定分步查询调用的方法

column:指定分步查询传递的参数

​ 传递单个:直接写列名,表示将这列的值作为参数传递给下一个查询

​ 传递多个:column="{prop1=col1,prop2=col2}",下一个查询使用prop1、prop2取值

@Mapper
public interface CustomerAndOrdersStep {
    List<Order> getOrderListByCustomerId(long cId);
    Customer getCustomerById(long id);
    
    Customer getCustomerAndOrderStepById(long id);
}

MyBatis 映射文件:

<!--根据客户id查询所有订单-->
<select id="getOrderListByCustomerId" resultType="com.chs.bean.Order">
    select * from t_order where customer_id = #{cId}
</select>
<!--根据客户id查询客户信息-->
<select id="getCustomerById" resultType="com.chs.bean.Customer">
    select * from t_customer where id = #{id}
</select>
<!-- 自定义结果集,异步查询 -->
<resultMap id="CustomerAndOrderRM" type="com.chs.bean.Customer">
   <id column="customer_id" property="id"></id>
   <result column="customer_name" property="customerName"></result>
   <result column="phone" property="phone"></result>
   <collection property="orderList" ofType="com.chs.bean.Order"
               select="getOrderListByCustomerId"		<!-- 指定继续查询的方法名 -->
               column="id" ></collection>      <!-- 传递继续查询的参数值 -->
</resultMap>

<!--使用自定义结果集-->
<select id="getCustomerAndOrderStepById" resultMap="CustomerAndOrderRM">
     select * from t_customer where id = #{id}
</select>

超级分步

分步的分步

    <!--   按照id查询客户 -->
<select id="getCustomerById" resultMap="CustomerOrdersStepRM">
     select *
     from t_customer
     where id = #{id}
</select>

<!--   按照客户id查询他的所有订单  resultType="com.atguigu.mybatis.bean.Order" -->
<select id="getOrdersByCustomerId" resultType="com.atguigu.mybatis.bean.Order">
     select *
     from t_order
     where customer_id = #{cId}
</select>


<!--   分步查询的自定义结果集: -->
<resultMap id="CustomerOrdersStepRM" type="com.atguigu.mybatis.bean.Customer">
    <id column="id" property="id"></id>
    <result column="customer_name" property="customerName"></result>
    <result column="phone" property="phone"></result>
    <collection property="orders"
                select="com.atguigu.mybatis.mapper.OrderCustomerStepMapper.getOrdersByCustomerId"
                column="id">
     </collection>
        <!--    告诉MyBatis,封装 orders 属性的时候,是一个集合,
                但是这个集合需要调用另一个 方法 进行查询;select:来指定我们要调用的另一个方法
                column:来指定我们要调用方法时,把哪一列的值作为传递的参数,交给这个方法
                   1)、column="id": 单传参:id传递给方法
                   2)、column="{cid=id,name=customer_name}":多传参(属性名=列名);
                        cid=id:cid是属性名,它是id列的值
                        name=customer_name:name是属性名,它是customer_name列的值
        -->

</resultMap>
<select id="getCustomerByIdAndOrdersStep" resultMap="CustomerOrdersStepRM">
    select *
    from t_customer
    where id = #{id}
</select>


<!--   分步查询:自定义结果集;封装订单的分步查询  -->
<resultMap id="OrderCustomerStepRM" type="com.atguigu.mybatis.bean.Order">
     <id column="id" property="id"></id>
     <result column="address" property="address"></result>
     <result column="amount" property="amount"></result>
     <result column="customer_id" property="customerId"></result>
        <!--       customer属性关联一个对象,启动下一次查询,查询这个客户 -->
     <association property="customer"
                  select="com.atguigu.mybatis.mapper.OrderCustomerStepMapper.getCustomerById"
                  column="customer_id">
   	 </association>
</resultMap>
<select id="getOrderByIdAndCustomerStep" resultMap="OrderCustomerStepRM">
        select *
        from t_order
        where id = #{id}
</select>
<!--   查询订单 + 下单的客户 + 客户的其他所有订单 -->
<select id="getOrderByIdAndCustomerAndOtherOrdersStep"
        resultMap="OrderCustomerStepRM">
  	select * from t_order where id = #{id}
</select>

延迟加载

分步查询有时候并不需要立即运行,我们希望在用到的时候再去查询,可以开启延迟加载的功能

全局配置:

  • mybatis.configuration.lazy-loading-enabled=true
  • mybatis.configuration.aggressive-lazy-loading=false

MyBatis 动态SQL

MyBatis 的动态 SQL 功能允许开发者根据不同的条件动态生成 SQL 语句。这种灵活性使得在处理复杂查询时,可以根据用户输入或其他条件来构建 SQL 语句,从而提高了代码的可维护性和可读性。

if和where标签

<if>:根据条件判断是否包含某个 SQL 片段

where:标签会自动去掉“标签体内前面多余的and/or等

<select id="selectEmployeeByCondition" resultType="employee">
    select emp_id,emp_name,emp_salary from t_emp
    <!-- where标签会自动去掉“标签体内前面多余的and/or” -->
    <where>
        <!-- 使用if标签,让我们可以有选择的加入SQL语句的片段。这个SQL语句片段是否要加入整个SQL语句,就看if标签判断的结果是否为true -->
        <!-- 在if标签的test属性中,可以访问实体类的属性,不可以访问数据库表的字段 -->
        
        <if test="empName != null">
            <!-- 在if标签内部,需要访问接口的参数时还是正常写#{} -->
            or emp_name=#{empName}
        </if>
        <if test="empSalary &gt; 2000">
            or emp_salary>#{empSalary}
        </if>
        <!--
         第一种情况:所有条件都满足 WHERE emp_name=? or emp_salary>?
         第二种情况:部分条件满足 WHERE emp_salary>?
         第三种情况:所有条件都不满足 没有where子句
         -->
    </where>
</select>

set标签

使用set标签动态管理set子句,并且动态去掉两端多余的逗号

<update id="updateEmployeeDynamic">
    update t_emp
    <!-- set emp_name=#{empName},emp_salary=#{empSalary} -->
    <!-- 使用set标签动态管理set子句,并且动态去掉两端多余的逗号 -->
    <set>
        <if test="empName != null">
            emp_name=#{empName},
        </if>
        <if test="empSalary &lt; 3000">
            emp_salary=#{empSalary},
        </if>
    </set>
    where emp_id=#{empId}
    <!--
         第一种情况:所有条件都满足 SET emp_name=?, emp_salary=?
         第二种情况:部分条件满足 SET emp_salary=?
         第三种情况:所有条件都不满足 update t_emp where emp_id=?
            没有set子句的update语句会导致SQL语法错误
     -->
</update>

trim标签

使用trim标签控制条件部分两端是否包含某些字符

  • prefix属性:指定要动态添加的前缀
  • suffix属性:指定要动态添加的后缀
  • prefixOverrides属性:指定要动态去掉的前缀,使用“|”分隔有可能的多个值
  • suffixOverrides属性:指定要动态去掉的后缀,使用“|”分隔有可能的多个值
<select id="selectEmployeeByConditionByTrim" resultType="com.chs.mybatis.entity.Employee">
    select emp_id,emp_name,emp_age,emp_salary,emp_gender
    from t_emp
    <!-- prefix属性指定要动态添加的前缀 -->
    <!-- suffix属性指定要动态添加的后缀 -->
    <!-- prefixOverrides属性指定要动态去掉的前缀,使用“|”分隔有可能的多个值 -->
    <!-- suffixOverrides属性指定要动态去掉的后缀,使用“|”分隔有可能的多个值 -->
    <!-- 当前例子用where标签实现更简洁,但是trim标签更灵活,可以用在任何有需要的地方 -->
    <trim prefix="where" suffixOverrides="and|or">
        <if test="empName != null">
            emp_name=#{empName} and
        </if>
        <if test="empSalary &gt; 3000">
            emp_salary>#{empSalary} and
        </if>
        <if test="empAge &lt;= 20">
            emp_age=#{empAge} or
        </if>
        <if test="empGender=='male'">
            emp_gender=#{empGender}
        </if>
    </trim>
</select>

choose/when/otherwise标签

在多个分支条件中,仅执行一个。

  • 从上到下依次执行条件判断
  • 遇到的第一个满足条件的分支会被采纳
  • 被采纳分支后面的分支都将不被考虑
  • 如果所有的when分支都不满足,那么就执行otherwise分支
<select id="selectEmployeeByConditionByChoose" resultType="com.chs.mybatis.entity.Employee">
    select emp_id,emp_name,emp_salary from t_emp
    where
    <choose>
        <when test="empName != null">emp_name=#{empName}</when>
        <when test="empSalary &lt; 3000">emp_salary &lt; 3000</when>
        <otherwise>1=1</otherwise>
    </choose>
    
    <!--
     第一种情况:第一个when满足条件 where emp_name=?
     第二种情况:第二个when满足条件 where emp_salary < 3000
     第三种情况:两个when都不满足 where 1=1 执行了otherwise
     -->
</select>

foreach标签

用于遍历集合

用批量插入举例

<!--
    collection属性:要遍历的集合
    item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象
    separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符
    open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串
    close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串
    index属性:这里起一个名字,便于后面引用
        遍历List集合,这里能够得到List集合的索引值
        遍历Map集合,这里能够得到Map集合的key
 -->
<foreach collection="empList" item="emp" separator="," open="values" index="myIndex">
    <!-- 在foreach标签内部如果需要引用遍历得到的具体的一个对象,需要使用item属性声明的名称 -->
    (#{emp.empName},#{myIndex},#{emp.empSalary},#{emp.empGender})
</foreach>
批量更新时需要注意

上面批量插入的例子本质上是一条SQL语句,而实现批量更新则需要多条SQL语句拼起来,用分号分开。也就是一次性发送多条SQL语句让数据库执行。此时需要在数据库连接信息的URL地址中设置:allowMultiQueries=true

spring.datasource.url=jdbc:mysql:///mybatis-example?allowMultiQueries=true

对应的foreach标签如下:

<update id="updateEmployeeBatch">
    <foreach collection="empList" item="emp" separator=";">
        update t_emp set emp_name=#{emp.empName} where emp_id=#{emp.empId}
    </foreach>
</update>

关于foreach标签的collection属性

如果没有给接口中List类型的参数使用@Param注解指定一个具体的名字,那么在collection属性中默认可以使用collection或list来引用这个list集合。这一点可以通过异常信息看出来:

Parameter 'empList' not found. Available parameters are [arg0, collection, list]

在实际开发中,为了避免隐晦的表达造成一定的误会,建议使用@Param注解明确声明变量的名称,然后在foreach标签的collection属性中按照@Param注解指定的名称来引用传入的参数。

sql片段

抽取重复的SQL片段

<!-- 使用sql标签抽取重复出现的SQL片段 -->
<sql id="mySelectSql">
    select emp_id,emp_name,emp_age,emp_salary,emp_gender from t_emp
</sql>

引用已抽取的SQL片段

<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>

特殊字符

以后在xml中,以下字符需要用转义字符,不能直接写

原始字符 转义字符
& &amp;
< &lt;
> &gt;
" &quot;
' &apos;

MyBais-缓存机制

MyBatis 拥有二级缓存机制:

一级缓存默认开启; 事务级别:当前事务共享。

默认事务期间,会开启事务级别缓存;

  • 同一个事务期间,前面查询的数据,后面如果再要执行相同查询,会从一级缓存中获取数据,不会给数据库发送SQL
@Transactional //默认 可重复读
public void find(){
  //方法体
}

//有时候缓存会失效(缓存不命中)。
//失效几种情况
// 1、查询的东西不一样。
// 2、两次查询之间,进行了一次增删改(由于增删改会引起数据库变化,Mybatis认为,数据有可能变了,它就要再发一次查询)

二级缓存需要手动配置开启:所有事务共享

<!--   cache功能开启:所有的查询都会共享到二级缓存 -->
<mapper namespace="com.example.Mapper">  
    <cache/>  
    <!-- 其他 SQL 语句配置 -->  
</mapper>

缓存中有就不用查数据库:

L1~LN:N级缓存

​ 数字越小离我越近,查的越快。存储越小,造价越高。

​ 数字越大离我越远,查的越慢。存储越大,造价越低。

插件机制

MyBatis 底层使用 拦截器机制提供插件功能,方便用户在SQL执行前后进行拦截增强。

拦截器:Interceptor

拦截器可以拦截四大对象的执行

ParameterHandler:处理SQL的参数对象

ResultSetHandler:处理SQL的返回结果集

StatementHandler:数据库的处理对象,用于执行SQL语句

Executor:MyBatis的执行器,用于执行增删改查操作

PageHelper 分页插件

PageHelper 是一个 MyBatis 的分页插件,广泛用于简化分页查询的操作。在使用 MyBatis 进行数据访问时,PageHelper 能够让你快速实现数据的分页功能,提高应用程序的性能与用户体验。

添加依赖

<dependency>  
    <groupId>com.github.pagehelper</groupId>  
    <artifactId>pagehelper-spring-boot-starter</artifactId>  
    <version>最新版</version> <!-- 请替换为最新版本 -->  
</dependency>

创建分页插件对象

@MapperScan("com.chs.mybatis.mapper") //批量只扫描mapper
@Configuration
public class MyBatisConfig {
    @Bean
    PageInterceptor pageInterceptor(){
        //1、创建 分页插件 对象
        PageInterceptor interceptor = new PageInterceptor();
        //2、设置 参数
        //.......
        Properties properties = new Properties();
        //设置页码超出范围=》自动规范
        properties.setProperty("reasonable", "true");
        interceptor.setProperties(properties);
        return interceptor;
    }

}

使用 PageHelper 进行分页查询

紧跟着 startPage (num)之后 的方法就会执行自动的 SQL 分页查询

原理:拦截器;
原业务底层sql:select * from user;
拦截器做两件事:
1)、统计这个表的总数量
2)、给原业务底层SQL 动态拼接上 limit (startPage,pageSize);

ThreadLocal: 同一个线程共享数据

  • 第一个查询从 ThreadLocal 中获取到共享数据,执行分页
  • 第一个执行完会把 ThreadLocal 分页数据删除
  • 以后的查询,从 ThreadLocal 中拿不到分页数据,就不会分页
import com.github.pagehelper.PageHelper;  
import com.github.pagehelper.PageInfo;  

import java.util.List;  

public List<User> getUsers(int pageNum, int pageSize) {  
    // 开始分页  
    PageHelper.startPage(pageNum, pageSize);  //紧跟着 startPage 之后 的方法就会执行的 SQL 分页查询
    // 执行查询  
    List<User> users = userMapper.selectAll(); // 假设在 UserMapper 中定义了这个方法  

    // 封装分页信息  
    PageInfo<User> pageInfo = new PageInfo<>(users);  
    return pageInfo.getList(); // 获取当前页的记录  
}

mybatisx - 逆向生成

IDEA 安装 mybatisx 插件,即可根据数据库表一键生成常用CRUD

首先使用 IntelliJ IDEA连接数据库

image-20240907165533055

使用逆向工程

image_DkwlIx_BM9

image_dJvZP76xYm

image_KXYfK5CQd-

MyBatis总结

核心点 掌握目标
mybatis基础 使用流程, 参数输入,#{} ${},参数输出
mybatis多表 实体类设计,resultMap多表结果映射
mybatis动态语句 Mybatis动态语句概念, where , if , foreach标签
mybatis扩展 Mapper批量处理,分页插件,逆向工程
posted @ 2024-09-25 09:43  CH_song  阅读(0)  评论(0编辑  收藏  举报