MyBatis学习总结

一.基础使用:

1.MyBatis日志配置

<settings>
  <!-- SLF4J 选择slf4j输出! -->
  <setting name="logImpl" value="SLF4J"/>
</settings>

2.数据输入

1)#{}和${}

#{key}:占位符+赋值 emp_id = ? ,? = 赋值

${key}:字符串拼接 emp_id = ""+id ?只能替代值的位置,不能替代容器名(列名,标签,关键字)

select * from 表 where 列名是动态的${columName} = 动态的值 #{columValue}

2)单个简单类型参数

单个简单类型参数,在#{}中可以随意命名,但是没有必要。通常还是使用和接口方法参数同名。

3)实体类类型参数

Mybatis会根据#{}中传入的数据,加工成getXxx()方法,通过反射在实体类对象中调用这个方法,从而获取到对应的数据。填充到#{}解析后的问号占位符这个位置。

4)零散的简单类型参数
int updateEmployee(@Param("empId") Integer empId,@Param("empSalary") Double empSalary);
<update id="updateEmployee">
  update t_emp set emp_salary=#{empSalary} where emp_id=#{empId}
</update>
4)Map类型参数

#{}中写Map中的key

有很多零散的参数需要传递,但是没有对应的实体类类型可以使用。使用@Param注解一个一个传入又太麻烦了。所以都封装到Map中。

int updateEmployeeByMap(Map<String, Object> paramMap);
<update id="updateEmployeeByMap">

  update t_emp set emp_salary=#{empSalaryKey} where emp_id=#{empIdKey}

</update>

 3.数据输出

 1).单个简单类型

Mybatis 内部给常用的数据类型设定了很多别名。 以 int 类型为例,可以写的名称有:int、integer、Integer、java.lang.Integer、Int、INT、INTEGER 等等。

int selectEmpCount();
<select id="selectEmpCount" resultType="int">
  select count(*) from t_emp
</select>
 2).返回实体类对象

1.通过给数据库表字段加别名,让查询结果的每一列都和Java实体类中属性对应起来。

2.增加全局配置自动识别对应关系(自动识别驼峰式命名规则)

3.使用resultMap

 3).返回Map类型

如果没有对应的实体类,可以用实体类接收,key就是查询的的列,value就是查询的值

<select id="selectEmpNameAndMaxSalary" resultType="map">
        <!-- Map<String,Object> selectEmpNameAndMaxSalary(); -->
        <!-- 返回工资最高的员工的姓名和他的工资 -->
        SELECT
        emp_name 员工姓名,
        emp_salary 员工工资,
        (SELECT AVG(emp_salary) FROM t_emp) 部门平均工资
        FROM t_emp WHERE emp_salary=(
        SELECT MAX(emp_salary) FROM t_emp
        )
    </select>
 4).返回List类型

返回值是集合,不需要指定集合类型,只需要指定泛型即可

selectList集合: selectOne(查询单个)调用selectList(查询集合)

 5).返回主键值
自增长主键类型

在插入数据后,我们可能需要立即获取这个自动生成的主键值,以便进行后续的操作,如关联查询或日志记录。

useGeneratedKeys属性就是为了支持这一需求而设计的。

Mybatis是将自增主键的值设置到实体类对象中,即使这个类中没setter方法也能成功

 <!--
    主键回显 获取插入数据的主键
    useGeneratedKeys="true":想要数据库自动增强的主键值
    keyColumn="emp_id"主键列的值
    keyProperty="empId":接收主键列的属性,在原对象上接收
    -->
    <insert id="insertEmp" useGeneratedKeys="true" keyColumn="emp_id" keyProperty="empId">
        insert into t_emp(emp_name,emp_salary)
        values(#{empName},#{empSalary});
    </insert>
非自增主键维护

而对于不支持自增型主键的数据库(例如 Oracle)或者字符串类型主键,则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用!

    <insert id="inserTeacher" >
        <!--
        插入之前,先指定一sql语句
        order="before|after" sql语句是在插入语句之前还是之后执行
        resultType = 返回值类型
        keyProperty = 查询结果给哪个属性赋值
        -->
        <selectKey order="BEFORE" resultType="string" keyProperty="tId">
            select  REPLACE(UUID(),'-','')
        </selectKey>
        insert into teacher(t_id,t_name) value(#{tId},#{tName});
    </insert>
6).实体类属性和数据库字段对应关系
方法一:取别名

用sql语句将字段的别名设置成和实体类属性一致。

resultType按照规则自动映射,只能映射一层,多表查询的时候结果无法映射比如雇员中如果依赖了其他对象

<!-- 编写具体的SQL语句,使用id属性唯一的标记一条SQL语句 -->
<!-- resultType属性:指定封装查询结果的Java实体类的全类名 -->
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">

  <!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
  <!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
  select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{maomi}

</select>
方法二:全局配置自动识别驼峰式命名规则
<!-- 使用settings对Mybatis全局进行设置 -->
<settings>

  <!-- 将xxx_xxx这样的列名自动映射到xxXxx这样驼峰式命名的属性名 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>
方法三:使用resultMap

默认情况下,resultMap会自动映射单层的result标签(列名相同或者开启驼峰式)


    <!--resultMap标签,自己定义映射规则
      id标识 ->
      type ->具体的返回值类型全限定符/别名 集合只写泛型即可
        <id 主键映射关系
        <result 普通列的映射关系
    -->
    <resultMap id="tMap" type="teacher">
        <id column="t_id" property="tId"/>
        <result column="t_name" property="tName"/>
    </resultMap>

<select id="selectEmployeeByRM" resultMap="tMap">

  select t_id,t_name from teacher where t_id=#{tId}

</select>

二.多表查询

@Data
public class Order {
    private Integer orderId;
    private String orderName;
    private Integer customerId;
    private Customer customer;// 体现的是对一的关系

}
@Data
public class Customer {

    private Integer customerId;
    private String customerName;
    private List<Order> orderList;// 体现的是对多的关系

}

1.一对一

根据id查询订单以及其订单关联的用户信息

   <resultMap id="orderMap" type="order">
        <!--第一层属性order-->
        <id column="order_id" property="orderId"/>
        <result column="order_name" property="orderName"/>
        <result column="customer_id" property="customerId"/>
        <!--第二层-->
        <association property="customer" javaType="customer">
            <id column="customer_id" property="customerId"/>
            <result column="customer_name" property="customerName"/>
        </association>
    </resultMap>

    <select id="queryOrderByID" resultMap="orderMap">
        select * from t_order tor join t_customer tur on order_id= #{id};
    </select>

2.多对多

查询客户以及客户对应的订单信息

  <resultMap id="customerMap" type="customer">
        <id column="customer_id" property="customerId"/>
        <result column="customer_name" property="customerName"/>
        <collection property="orderList" ofType="order">
            <id column="order_id" property="orderId"/>
            <result column="order_name" property="orderName"/>
        </collection>
    </resultMap>
    <select id="queryList" resultMap="customerMap">
        select * from t_order tor join t_customer tur
        on tor.customer_id = #{id};
    </select>

3.优化

setting属性:autoMappingBehavior

可选值:NONE, PARTIAL, FULL

默认:PARTIAL

作用:指定 MyBatis 应如何自动映射列到字段或属性。 NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。

<!--开启resultMap自动映射 -->
<setting name="autoMappingBehavior" value="FULL"/>

会自动帮我们映射result标签的属性和列

<resultMap id="teacherMap" type="teacher">
    <id property="tId" column="t_id" />
    <!-- 开启自动映射,并且开启驼峰式支持!可以省略 result!-->
<!--        <result property="tName" column="t_name" />-->
    <collection property="students" ofType="student" >
        <id property="sId" column="s_id" />
<!--            <result property="sName" column="s_name" />-->
    </collection>
</resultMap>

三.动态查询

1.if and where

   <!--
    如果传入属性,就判断相等,否则不加对应的条件
    where标签的作用有两个
    1.自动添加where关键字 where内部有任何一个if满足,自动添加where
    2.自动去掉多余的 and 和 or
    -->

    <select id="query" resultType="employee">
        select * from t_emp where
        <where>
            <if test="name !=null">
                emp_name=#{name}
            </if>
            <if test="salary!=null and salary > 100">
                and emp_salary = #{salary};
            </if>
        </where>
    </select>

2.set

set:1.自动去掉多余 ,

      2.自动添加set关键字

      3.必须保证至少一个if成立,否则报错

 <update id="update">
        update t_emp
        <set>
            <if test="empName != null">
                emp_name=#{empName},
            </if>
            <if test="empSalary != null">
                emp_salary=#{empSalary}
            </if>
        </set>
        where emp_id = #{empId}
    </update>

3.trim

prefix属性:指定要动态添加的前缀
suffix属性:指定要动态添加的后缀
prefixOverrides属性:指定要动态去掉的前缀,使用“|”分隔有可能的多个值
suffixOverrides属性:指定要动态去掉的后缀,使用“|”分隔有可能的多个值

<select id="query" resultType="employee">
        select * from t_emp
        <trim prefix="where" prefixOverrides="and | or">
            <if test="name !=null">
                emp_name=#{name}
            </if>
            <if test="salary!=null and salary > 100">
                and emp_salary = #{salary};
            </if>
        </trim>
    </select>

4.choose/when/otherwise

从上到下依次执行条件判断
遇到的第一个满足条件的分支会被采纳
被采纳分支后面的分支都将不被考虑
如果所有的when分支都不满足,那么就执行otherwise分支

根据两个条件查询,如果姓名不为Null,使用姓名查询,如果姓名不为null,使用薪水查询

<select id="queryChoose" resultType="employee">
        select * from t_emp where
        <choose>
            <when test="name !=null">
                emp_name=#{name}
            </when>
            <when test="salary!=null and salary > 100">
                emp_salary = #{salary};
            </when>
            <otherwise>1=1</otherwise>
        </choose>
    </select>

5.foreach

collection属性:要遍历的集合 item属性:遍历集合的过程中能得到每一个具体对象,在item属性中设置一个名字,将来通过这个名字引用遍历出来的对象

separator属性:指定当foreach标签的标签体重复拼接字符串时,各个标签体字符串之间的分隔符

open属性:指定整个循环把字符串拼好后,字符串整体的前面要添加的字符串 close属性:指定整个循环把字符串拼好后,字符串整体的后面要添加的字符串

index属性:这里起一个名字,便于后面引用 遍历List集合,这里能够得到List集合的索引值 遍历Map集合,这里能够得到Map集合的key

1).查询:
  List<Employee> queryBatch(@Param("ids") List<Integer> ids);
   <select id="queryBatch" resultType="employee">
        select * from t_emp
        where emp_id in
        <foreach collection="ids" open="(" separator="," close=")" item="id">
            #{id}
        </foreach>
    </select>
2).插入: 
 int insertBatch(@Param("list") List<Employee> employeeList);
  <insert id="insertBatch">
        insert into t_emp(emp_name,emp_salary)
        values
        <foreach collection="list" separator="," item="employee">
            (#{employee.empName},#{employee.empSalary})
        </foreach>
    </insert>
3).更新:

一次性发送多条SQL语句让数据库执行。此时需要在数据库连接信息的URL地址中设置

xx.url=jdbc:mysql:///xxxxx?allowMultiQueries=true

<!-- int updateEmployeeBatch(@Param("empList") List<Employee> empList) -->
<update id="updateEmployeeBatch">
    <foreach collection="empList" item="emp" separator=";">
        update t_emp set emp_name=#{emp.empName} where emp_id=#{emp.empId}
    </foreach>
</update>

6.sql片段

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

<!-- 使用include标签引用声明的SQL片段 -->
<include refid="mySelectSql"/>
<sql id="selectSql">
    insert into t_emp(emp_name,emp_salary) values
</sql>
    <insert id="insertBatch">
      <include refid="selectSql"/>
        <foreach collection="list" separator="," item="employee">
            (#{employee.empName},#{employee.empSalary})
        </foreach>
    </insert>

四.高级拓展

1.Mapper批量映射优化

Mapper 配置文件很多时,在全局配置文件中一个一个注册太麻烦,希望有一个办法能够一劳永逸。

此时这个包下的所有 Mapper 配置文件将被自动加载、注册,比较方便。

<mappers>
    <package name="com.yan.mapper"/>
</mappers>

要求:

1.Mapper 接口和 Mapper 配置文件名称一致

2.Mapper 配置文件放在 Mapper 接口所在的包内(可以在sources下创建mapper接口包一致的文件夹结构存放mapperxml文件)

 

2.插件机制和分页插件

pom.xml引入依赖

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.11</version>
</dependency>

mybatis-config.xml配置分页插件

<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="helperDialect" value="mysql"/>
    </plugin>
</plugins>
 EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        //调用之前,设置当前是第几页,每页显示多少个
        PageHelper.startPage(1, 2);
        List<Employee> emps = mapper.queryList();
        //将查询数据封装到一个PageInfo分页实体类(一共多少页,一共多少条)
        PageInfo<Employee> pageInfo = new PageInfo<>(emps);
        //当前页数据
        List<Employee> list1= pageInfo.getList();
        //当前页的数据
        int pages = pageInfo.getPages();
        //获取总条数
        long total = pageInfo.getTotal();

3.逆向工程

MyBatis 的逆向工程是一种自动化生成持久层代码和映射文件的工具,它可以根据数据库表结构和设置的参数生成对应的实体类、Mapper.xml 文件、Mapper 接口等代码文件,简化了开发者手动生成的过程。逆向工程使开发者可以快速地构建起 DAO 层,并快速上手进行业务开发。

逆向工程只能生成单表的crud操作,多表仍需要我们自己编写!

1).安装MyBatisX插件

2). 使用 IntelliJ IDEA连接数据库
3).填写信息

  • 16
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值