Wallace's Blog

vuePress-theme-reco Wallace Xu    2019 - 2024
Wallace's Blog Wallace's Blog

Choose mode

  • dark
  • auto
  • light
主页
分类
  • 个人随笔
  • 知海拾贝
  • LeetCode
  • 剑指Offer
  • 自学技术
标签
时间轴
联系我
  • GitHub (opens new window)
  • 邮箱 (opens new window)
author-avatar

Wallace Xu

146

文章

53

标签

主页
分类
  • 个人随笔
  • 知海拾贝
  • LeetCode
  • 剑指Offer
  • 自学技术
标签
时间轴
联系我
  • GitHub (opens new window)
  • 邮箱 (opens new window)
  • 自学技术

    • Mybatis复习
    • Redis学习
    • SSM框架开发学习笔记-Spring MVC部分
    • SSM框架开发学习笔记-Mybatis部分
    • SSM框架开发学习笔记-Spring部分
    • SSM框架开发学习笔记-SSM整合
    • SSM组件与原理深入学习
    • 手写简易ORM框架学习笔记

Mybatis复习

vuePress-theme-reco Wallace Xu    2019 - 2024

Mybatis复习

Wallace Xu 2021-08-09 ORM

# Mybatis简介

# 概述

  • Mybatis作用
    • Mybatis是支持定制化SQL、存储过程以及高级映射的持久层半自动化框架
    • Mybatis避免了几乎所有的JDBC代码、手动设置参数以及获取结果集。
    • Mybatis使用简单的XML用于配置和原始映射,将接口和Java的POJO类映射成数据库中的记录。
    • 开发者只需要关注SQL本身,而无需花费精力处理注册驱动、创建connection、statement、设置参数等JDBC中繁杂的过程。
  • 为什么要使用Mybatis
    • JDBC:SQL加载在Java代码中,耦合度高,硬编码不易维护,需要自行创建Connection等对象,流程繁琐。
    • Hibernate:复杂的SQL处理不便、自动生成的SQL不容易做优化,全映射无法只映射部分字段导致数据库性能下降。
    • Mybatis:是半自动化的,开发者可以优化SQL。
  • Mybatis使用流程
    1. 在项目中引入Mybatis核心包和依赖包,编辑核心XML配置文件,添加数据库连接信息
    2. 创建与数据库中表对应的Java POJO
    3. 创建Mapper配置文件,并在核心配置文件中注册这些Mapper
    4. 创建Mybatis提供的SqlSessionFactory工厂,执行SQL语句,关闭SqlSession

# Mybatis核心API

  • SqlSessionFactoryBuilder:用于读取核心配置文件,创建SqlSessionFactory,创建完毕后就不需要了。
  • SQLSessionFactory:创建SqlSession的工厂,是一个接口,定义了openSession的不同重载方法。
  • SqlSession:是连接到数据库的一个会话,定义了数据库的操作方法如SelectOne()、SelectList()等,是线程不安全的。

# MyBatis CRUD

想要查看执行的详情,可以在配置中settings标签内加入下面的setting:<setting name="logImpl" value="STDOUT_LOGGING"/>。

# 查询

下面是一个mapper例子:

<mapper namespace="com.company.CustomerMapper">
    <!--根据ID查询用户-->
    <select id="queryCustomerById" parameterType="Int" resultType="com.company.pojo.Customer">
        SELECT * FROM `mydb`.`customer` WHERE cust_id = #{cust_id}
    </select>

    <!--根据用户名模糊查询用户-->
    <select id="queryCustomerByName" parameterType="String" resultType="com.company.pojo.Customer">
        SELECT * FROM `mydb`.`customer` WHERE cust_name LIKE '%${value}%'
    </select>
</mapper>
1
2
3
4
5
6
7
8
9
10
11

在执行查询时,#{}中的内容会被占位符?替代,传入参数时会自动加上引号'',并且可以防止SQL注入。

${}表示拼接字符串,传入的内容不会做类型转换,但不能防止SQL注入。在进行模糊查询时,除了像例子中那样使用'%${value}%'的方式,还可以使用#{value}并将传入的String直接改为%value%以规避SQL注入的风险。

# 插入

<mapper namespace="com.company.CustomerMapper">
    <insert id="addCustomer" parameterType="com.company.pojo.Customer">
        <!--在插入后获取最后一个id存回对象中-->
        <selectKey keyColumn="cust_id" keyProperty="cust_id" reultType="Integer" order="AFTER">
            SELECT last_insert_id()
        </selectKey>

        INSERT INTO `mydb`.`customer`(cust_name, cust_profession, cust_phone) VALUES(#{cust_name}, #{cust_profession}, #{cust_phone})
    </insert>
</mapper>
1
2
3
4
5
6
7
8
9
10

在对数据库的内容进行改动时需要自己提交事务:

public void insertTest() {
    SqlSession sqlSession = MyBatisUtils.openSession();
    Customer customer = new Customer("Judy", "Teacher", "13912341234");
    sqlSession.insert("addCustomer", customer);
    sqlSession.commit(); //手动提交
    sqlSession.close();
    //此时customer对象中已经被写入了获取到的id
}
1
2
3
4
5
6
7
8

# 更新与删除

<mapper namespace="com.company.CustomerMapper">
    <update id="updateCustomer" parameterType="com.company.pojo.Customer">
        UPDATE `mydb`.`customer` SET cust_name=#{cust_name} WHERE cust_id=#{cust_id}
    </update>

    <delete id="deleteCustomer" parameterType="com.company.pojo.Customer">
        DELETE FROM `mydb`.`customer` WHERE cust_id=#{cust_id}
    </delete>
</mapper>
1
2
3
4
5
6
7
8
9

# MyBatis Mapper开发

尽管我们可以使用传统模式,定义DAO接口,再编写对应的实现类来调用MyBatis,但是MyBatis提供了动态代理的功能,使得我们只需要定义接口而无需自己编写实现类。不过需要遵从以下要求:

  • namespace必须要和Mapper接口类路径一致。
  • id必须和接口方法一致。
  • parameterType必须和接口方法参数类型一致。
  • resultType必须和接口方法返回值一致。
public void testMappepr() {
    SqlSession sqlSession = MyBatisUtils.openSession();
    CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);
    Customer customer = mapper.queryCustomerById(8);
}
1
2
3
4
5

在编写mapper时,如果传入的参数是单个,可以接受基本类型、对象类型(包括集合类型)的值,无需任何处理;而如果是任意多个参数,那么MyBatis会重新包装成map再传入,map的key是#{param1},#{param2},...或者#{arg0},#{arg1},...。

  • 如果想要自定义key的话可以在调用接口方法时在对应的参数前加上@Param("myKey")的注解。
  • 也可以自己创建一个Map,把参数的key和value放进去,那么mapper中就使用自定义的key名称获取value。
  • 还可以传入pojo类,此时使用的key名称就要和pojo类对应的的属性名相同。

在定义Mapper时,可以自定义resultMap,即指定把数据库中的哪一列封装成对象的哪个属性:

<reslutMap id="userMap" type="com.company.pojo.User">
    <!--id指定主键-->
    <id column="db_col_name" property="pojo_property_name"/> 
    <reslut column="db_col_name" property="pojo_property_name"/>
    <!--级联对象设置方法1-->
    <reslut column="db_col_name2" property="pojo_innerobj.propername"/>
    <!--级联对象设置方法2,一般使用这种方法-->
    <association property="pojo.innerobj" javaType="objClassType">
        <reslut column="db_col_name2" property="propername"/>
    </association>
</resultMap>
1
2
3
4
5
6
7
8
9
10
11

在涉及级联属性时,就必须使用resultMap来指定查询结果和属性的映射关系。association标签也常使用select属性进行用于分步查询(支持懒加载)。

涉及一对多的关系时,可以在resultMap中使用<collection>标签:

<collection property=" orders" ofType="Order">
    <id column="order_id" property=" order_id"/>
    <id column="order_name" property="order_name">
    <id column=" order_num" property="order_num">
</collection>

1
2
3
4
5
6

# MyBatis核心配置文件

在核心xml配置文件中,在<configuration>标签内,可以添加很多类型的配置信息,如果要添加则要按下面的顺序使用:

  • <properties>标签:定义很多<property name="aaa" value="long text">,使用键值对的方式添加属性。在下文中就可以通过"${aaa}"这样的形式代替填写值。实际开发中,往往会把单独要设置的属性存放到单独的.properties文件中,再在properties标签后加上resource="xxx.properties"就可以直接使用。
  • <settings>标签:会改变MyBatis运行时的行为,例如将下划线命名和驼峰命名进行转换等。详见:www.mybatis.org/mybatis-3/zh/configuration.html#settings
  • <typeAliases>标签:定义多个类型别名,可以使用<typaAlias alias="User" type="com.company.pojo.User">对单个类进行定义,也可以使用<package name="package name">为包下面的所有类设置别名(直接为类名),如果有子包的类名产生同名冲突可以使用@Alias("name")注解解决。
  • <typeHandlers>标签:定义类型处理器,用于转换数据库类型到Java类型,只在需要使用自定义类型的时候需要。
  • <plugins>标签:添加插件。
  • <environments>标签:可以定义多个不同的数据库环境,例如DEV开发环境和SIT测试环境等等,根据需要可以切换环境。实际开发中往往使用Spring来进行管理数据源和配置。
  • <databaseIDProvider>标签:指定使用的数据库类型,MyBatis可以根据不同的类型发送不同的SQL语句。定义后,可以在Mapper中通过databaseId="mysql"来声明仅在连接的数据库为Mysql时才执行该语句。
  • <mappers>标签: 用于加载映射文件,但映射文件的名称必须要和对应接口一致,并且要和接口存放于同一目录。可以用<mapper>标签指定单个要加载的映射文件,也可以使用<package name="pkg name">指定某个包下的所有映射文件。
我是Wallace欢迎你的关注
看板娘