MyBatis框架基础

MyBatis框架基础

MyBatis是一款优秀的持久层框架,它能够帮助Java开发者将业务逻辑与数据访问代码分离,具有简单,灵活,高效等特点,MyBatis使用xml或或注解的方式描述Java对象及其sql语句之间的映射关系,它支持多种数据库和操作方式,并且可以满足不同的数据访问要求,

MyBatis与JDBC的关系

JDBC的操作为例横向对比多次数据库访问的代码,

  • 每次执行的sql语句不同,或sql语句绑定的参数不同
  • 对结果集的操作逻辑不同

MyBatis的主要作用是编写访问数据库代码时,仅需要关注要执行的sql语句,参数与sql的绑定关系以及结果集的处理逻辑,其他部分由MyBatis完成,

MyBatis底层使用的任然是JDBC技术

Springboot项目使用MyBatis框架

1,引入mybatis的依赖

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

2,在springboot中配置mybatis框架

在src/main/resources文件夹中新建application.properties文件,该文件是Spring Boot项目的默认配置文件。在该文件中添加项目的配置信息:

# 数据库驱动:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 数据源名称
spring.datasource.name=defaultDataSource
# 数据库连接地址==>必须确保数据库中有这个数据库database1,或改为自己的数据库
spring.datasource.url=jdbc:mysql://localhost:3306/database1?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
# 数据库用户名&密码:
spring.datasource.username=root
spring.datasource.password=root
#指定Mybatis的Mapper文件
mybatis.mapper-locations=classpath:mappers/*xml

3,编写Mapper接口

  • 使用接口中的抽象方法来声明要执行的数据库操作

4,编写Mapper.xml映射文件或者在接口中添加注释

  • Mapper.xml文件用于描述java对象和sql语句之间的映射关系
  • 简单的sql语句可以通过在Mapper接口的方法付添加注解来实现

值的传递

在MyBatis中,值的传递主要是在java代码和sql语句之间传递参数值的过程,这些参数值可以单个值,也可以是数组,javabean对象;

  • 单值传递
  • 对象传递
  • Map传值
单值传递

如果程序中只有一个参数需要传递给SQL,可以直接作为方法参数传入。在SQL中可以使用任意名称获取这个参数。虽然名称可以任意,但通常仍然使用该属性的名称,以保证可读性。

例如,开发一个基于用户id查询用户信息的方法,可以在SQL中使用【#{参数名}】的方式来代表要传入的参数,具体的SQL语句如下:

select * from user where username = #{username}

此时,在Mapper接口的抽象方法中,可以声明一个对应类型的参数,名称与SQL中的参数名一致。MyBatis框架会自动获取调用方法时传入的参数,绑定到SQL语句的相应位置。

@Param注解

Mapper接口中某个方法接收了多个参数,需要在每个参数前添加@Param注解,手动添加参数映射的名称,否则会出现【BindingException: Parameter ‘xxx’ not found】的异常。

@Select("select * from user where " +
     "username=#{username} and password =#{password}")
User getUser(@Param("username") String username, @Param("password") String password);
对象传值

将多个参数传递给SQL时,可以使用对象来封装数据。

//mapper接口 
@Insert("insert  into user (username, password, role) " +
            "values (#{username}, #{password}, #{role})")
    int insertUser(User user);
//测试方法
 @Test
    void insertUser() {
        User user = new User();
        user.setUsername("dandy");
        user.setPassword("845665");
        user.setRole("普通用户");
        int row = userMapper.insertUser(user);
        System.out.println("row = " + row);
    }

#{}和${}

MyBatis中的#{}是用来替换SQL中的参数占位符。在执行SQL语句时,MyBatis会将占位符#{}替换成实际传递的参数值,并将其作为预编译语句的参数传递给数据库引擎。

#{}的核心特点是使用了预编译机制,相当于JDBC中的PreparedStatement:

  • 当传入的参数为字符串类型时,生成的SQL语句中会在参数值的前后自动添加单引号
  • 当传入的参数中包含SQL的特殊符号时,会被当成普通字符处理,可以避免SQL注入

在 MyBatis 中,${} 是一种参数占位符,用于将输入参数直接插入到 SQL 语句中。

${}的核心特点是没有使用预编译机制,相当于JDBC中的Statement。

  • 不论传入的参数是否为字符串类型,生成的SQL语句中都不会自动添加单引号
  • 当传入的参数中包含SQL的特殊符号时,特殊符号可能会生效,因此存在SQL注入的风险
  • 可以实现某些使用#{}无法实现的功能,如动态选择查询的列名

MyBatis常用标签

Mapper.xml文件

Mapper.xml是MyBatis中定义sql语句映射文件,可以在Mapper.xml文件中,可以指定数据库操作的sql语句,包括增删查改等操作的所有语句,此外,还可以定义查询结果映射规则,将查询结果映射为一个Java对象,

Mapper.xml文件的结构

<?xml version="1.0" encoding="UTF-8" ?>//xml文件声明
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  //文件格式声明
<mapper namespace="">
    
</mapper> 

namespace属性值需要匹配映射的接口位置,mapper标签内部的内容,例如 select 标签,用于接口中的抽象方法提供的映射的sql语句,是Mapper.xml的核心

步骤:

1.新建一个springboot项目,添加MySQL依赖和MyBatis框架的依赖

2.配置application.properties文件,添加相应的配置

3.创建实体类,此类的属性与数据库的某个表对应,注意下换线用驼峰命名

4.创建Mapper接口,声明必要的抽象方法,

添加@Mapper注解

5.在src/main/resorces目录下新建一个mapper文件夹,然后再此文件夹中新建一个Mapper.xml文件,并在文件夹下添加相应的操作数据库的语句

6.测试用例,在Mapper接口中,右键——》Generate——》Test…——》选择相应的抽象方法

添加@SpringBootTest注解和@Autowired(依赖注入)

下划线映射驼峰

数据库的表的字段使用下划线分割,例如 sml_title;此命名会与java的实体类造成不一致,从而导致MyBatis的查询结果属性值为null;

解决方案:

1、配置自动映射。

可以在application.properties文件中添加如下配置,该配置可以自动实现 sml_title到 smlTitle的转换

mybatis.configuration.map-underscore-to-camel-case=true

2.在SQL中通过配置别名手动建立映射。

select sml_title as smlTitle from news where id=#{id}

MyBatis基础标签

增删改查标签

在MyBatis的Mapper.xml中,通过各类标签来定义Mapper接口中的抽象方法映射的SQL语句。这些标签中,最为基础的是实现数据增、删、改、查操作的标签,分别

<insert>、<delete>、<update>、<select>。

共同的属性:

  • id:指定标签对应的抽象方法的名称,是标签的必要属性,同一个Mapper.xml文件中不能有两个标签拥有相同的id值
  • parameterType:输入参数的类型
  • statementType:指定是否使用预处理语句,可选值为 STATEMENT、PREPARED、CALLABLE,默认为 PREPARED

1、select标签

  • resultType:指定查询结果的数据类型,适用于查询结果与Java类完全匹配的情况
  • resultMap:指定查询结果映射的规则,适用于查询结果不能直接映射到某个Java类的情况

2、insert标签

  • useGeneratedKeys:表示是否使用自动生成的主键,默认为false。如果设置为true,则在插入数据时会返回主键值
  • keyProperty:表示将自动生成的主键值赋值给哪个属性,需要与useGeneratedKeys一起使用
模糊查询

在MyBatis中可有两种方法实现,

1.传值时在参数前后添加通配符(%),

2.在Mapper.xml的文件中sql语句中用concat函数实现,

select * from product where name like concat('%',#{name},'%')   
resultMap标签

当一个查询的结果无法简单的映射到一个Java类时,可以使用resultMap标签来配置查询结果到Java类的映射关系。无法通过下划线到驼峰的转换来建立映射关系。

简单来说:就是当java的实体类的属性与数据库表的字段名无法通过驼峰命名来解决时,java的实体类的属性为 a,可在此标签中用 b 来表示,

1.属性:

  • id:ResultMap的唯一标识符,在同一个命名空间下必须唯一
  • type:映射的java对象的完全限定名或类型别名

2.子标签:

  • id标签:用来指定主键的映射关系的,column属性的值是查询结果集中主键的列名,就是数据库表的字段名,property属性的值是java实体类的属性名
  • result标签:用来映射java类的属性和sql查询的结果集的列,column属性的值是查询结果集中主键的列名,就是数据库表的字段名,property属性的值是java实体类的属性名,

在select标签中。不在使用resultType属性,而是使用resultMap属性,属性值与定义好的resultMap标签的id值一致,

例子:

<?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">
<mapper namespace="com.example.boot.mapper1.UserMapper">
    <resultMap id="UserMap" type="com.example.boot1.entity.UserLog">
        <id column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="opt_type" property="optType"/>
        <result column="opt_create" property="created"/>
        <result column="opt_modified" property="updated"/>
    </resultMap>
    <!--查询所有用户-->
    <!--List<UserLog> listAll()-->
    <select id="listAll" resultMap="UserMap">
        select * from user
    </select>
</mapper>

封装关联查询

association标签

多对一

在 MyBatis 中,association 标签是用于定义对象之间关联关系的标签,主要用于处理多对一的关联查询结果映射。当在查询中需要将结果集中的某些列映射到嵌套的对象属性时,可以使用 association标签来实现。

属性:

  • property : 指定java类中的属性名,用于关联查询结果中的对应字段,
  • column:指定查询结果集合中的字段名,就是表的字段名
  • javaType:指定关联的java类型,代表关联属性的数据类型

association标签中可以添加id和result标签,作用与resultMap标签中的id和result标签相同。但是需要注意,association标签中的id和result标签是用于建立关联表列名到关联类属性名的映射。

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">
<mapper namespace="com.example.boot1.mapper.ProductMapper">
    <!--必须包含全部字段,即使列名和属性名一致也得显式声明-->
    <resultMap id="ProductMap" type="com.example.boot1.entity.Product">
        <id column="id" property="id"/>
        <result column="title" property="title"/>
        <result column="image" property="image"/>
        <result column="discount" property="discount"/>
        <result column="price" property="price"/>
        <result column="sales" property="sales"/>
        <result column="stock" property="stock"/>
        <result column="category_id" property="categoryId"/>
        <result column="views" property="views"/>
        <result column="created" property="created"/>
        <result column="updated" property="updated"/>
        <association property="category" javaType="com.example.boot1.entity.Category">
            <id column="category_id" property="id"/>
            <result column="name" property="name"/>
            <result column="display" property="display"/>
            <result column="order_num" property="orderNum"/>
            <result column="mc_created" property="created"/>
            <result column="mc_updated" property="updated"/>
        </association>
    </resultMap>
    <!--基于商品id查询商品信息-->
    <!--关联查询商品品类信息-->
    <!--Product getById(long id)-->
    <select id="getById" resultMap="ProductMap">
        select t1.id, title, image, discount, price, sales, stock, category_id, views, t1.created, t1.updated,name, display, order_num, t2.created as c_created, t2.updated as c_updated  from  product t1 join category t2
on t1.category_id = t2.id where t1.id = #{id}
    </select>
</mapper>
collection标签

一对多

属性:

  • property:表示待映射的Java类中的集合类型属性名称
  • ofType:表示集合中元素的Java类型

collection标签中可以添加id和result标签,作用与association标签中的id和result标签相同

Mapper.xml文件与上一个标签的大体一样,只是一个标签不一样

把javaType改为 ofType

复用sql语句

在 MyBatis 中,可以通过使用 sql标签和 include 标签来复用 SQL 语句。这两个标签的组合允许开发者在多个地方定义和引用相同的 SQL 片段,以提高代码的重用性和可维护性。

将Mapper.xml文件中的sql语句抽取出来,放入一个sql标签里面

<sql  id="yq">//id的属性名称随意取
select * from newss;
</sql>

//然后再select标签里添加如下,
<select id="" resultMap="">
<include refid="yq"/>
where id=#{id}

</select>

动态SQL

MyBatis动态SQL标签

MyBatis的动态SQL是一种允许在SQL语句中根据不同情况应用不同SQL片段的技术。这种技术可以帮助我们构建更加灵活和可维护的SQL语句,使得我们能够根据不同的查询条件来构建不同的SQL语句,从而避免了写许多冗余的SQL代码。

MyBatis提供了多种动态SQL标签,较为常用的四种如下所示:

1、if标签:用于判断某个条件是否满足,如果满足则执行某些操作。

2、choose标签:类似于Java中的switch语句,根据某个条件选择不同的分支,可以配合when和otherwise标签使用。

3、foreach标签:用于遍历集合(如List、Map等),根据集合中的元素动态构建SQL语句。

4、where标签:用于动态生成where语句,当where语句为空时,不会加入到最终的SQL语句中。

Mapper.xml文件例:if

<!--查询商品列表数据-->
    <!--List<Product> listProduct(@Param("title") String title
            , @Param("minPrice") Double minPrice
            , @Param("maxPrice") Double maxPrice)-->
    <select id="listProduct" resultMap="ProductMap">
       select * from product
        <where>
            <if test="title != null and title != ''">
                and title like concat('%', #{title}, '%') <!-- 模糊查询 -->
            </if>
            <if test="minPrice != null">
                and price &gt;= #{minPrice}<!-- &gt;是大于号 -->
            </if>
            <if test="maxPrice != null">
                and price &lt;= #{maxPrice}<!-- &lt;是小于号 -->
            </if>
        </where>
        order by price desc
    </select>

when标签示例

需求:开发一个查询商品列表的方法,接收字符串类型的orderType作为参数。其中:

  • 如果传入的参数为“sales”,则按照销量降序排列
  • 如果传入的参数为“views”,则按照浏览量降序排列
  • 其他情况下,按stock库存量降序排列
List<Product> listProductByOrder(String orderType);//mapper的接口的抽象方法

//Mapper.xml文件
<!--查询商品列表数据,返回排序后的数据-->
    <!--List<Product> listProductByOrder(String orderType)-->
    <select id="listProductByOrder" resultMap="ProductMap">
        select * from product
        order by
        <choose>
            <when test="orderType == 'sales'">
                sales
            </when>
            <when test="orderType == 'views'">
                views
            </when>
            <otherwise>
                stock
            </otherwise>
        </choose>
        desc
    </select> 
    
    
    //测试
    
    @Test
    void listProductByOrder() {
        List<Product> list = null;
        list = productMapper.listProductByOrder("");
        list.forEach( product -> {
            System.out.println(product.getId()+"\t\t"+product.getSales()
                    +"\t\t"+product.getViews()+"\t\t"+product.getStock());
        });
    }

foreach标签示例

 List<Product> listProductByCategory(@Param("cids") List<Integer> cids);
 
 
 <!--基于商品类型id的集合查询商品列表数据-->
    <!--List<Product> listProductByCategory(@Param("cids") List<Integer> cids)-->
    <select id="listProductByCategory" resultMap="ProductMap">
        select * from product
        where
          <choose>
              <when test="cids != null and cids.size() > 0">
                  category_id in
                  <foreach collection="cids" item="cid" open="(" close=")" separator=",">
                      #{cid}
                  </foreach>
              </when>
              <otherwise>
                  1 = 2
              </otherwise>
          </choose>
    </select>
    
     @Test
    void listProductByCategory() {
        List<Product> list = null;
        list = productMapper.listProductByCategory(List.of(1, 2));
        list.forEach( product -> {
            System.out.println(product.getId()+"\t\t"+product.getCategoryId());
        });
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>