欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java笔记:SpringBoot整合Mybatis需要注意的一些细节和ResultMap的用法

程序员文章站 2024-02-28 13:16:58
...

本文将讲一下SpringBoot整合Mybatis需要注意的一些细节,以及Mybatis中的resultMap结果映射集的用法。

ResultMap结果映射集可以说是mapper中最复杂的一个知识点,在此做个笔记以后可以翻阅,已经会了的朋友可以当做复习,还不会的朋友可以学习学习。



SpringBoot整合Mybatis


一、导入Maven依赖,配置参数



POM.xml 依赖:

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.1</version>
		</dependency>

		<!-- mysql的jdbc驱动包 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<!-- druid连接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.6</version>
		</dependency>
</dependencies>


application.yaml 参数配置:

spring:
  #数据库连接
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/DBName?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    username: root
    password: root
    #druid连接池
    druid:
      initial-size: 5 #连接池初始化大小
      min-idle: 10 #最小空闲连接数
      max-active: 20 #最大连接数
      web-stat-filter:
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据
      stat-view-servlet: #访问监控网页的登录用户名和密码
          login-username: druid
          login-password: druid


二、包结构和config配置

第一个细节:XXXMapper.java和XXXMapper.xml包路径要一致,即在java包结构src下和在静态资源resources文件下的路径要保持一致。

包结构:
Java笔记:SpringBoot整合Mybatis需要注意的一些细节和ResultMap的用法

User.java

import java.io.Serializable;
import java.util.Date;

import io.swagger.annotations.ApiModelProperty;

public class User implements Serializable {
    @ApiModelProperty(value = "用户ID")
    private Integer uId;

    @ApiModelProperty(value = "用户名")
    private String userName;
...
构造函数
getter/setter/toString...
}



第二个细节:使用Config类来进行一些必要的配置,开启自动扫描,按框架进行命名区分。

MyBatisConfig.java

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * MyBatis配置类,开启扫描
 * @author HT
 */
@Configuration
@EnableTransactionManagement
@MapperScan({"com.ht.test.dao","com.ht.test.mapper"})
public class MyBatisConfig {
}


三、创建mapper.java接口,编写mapper.xml查询配置文件

UserMapper.java

import com.ht.test.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;

/**
 * 用户信息自定义查询dao
 * @author HT
 */
public interface UserMapper {

    int insert(User user);

    //批量新增用户
    int insertUsers(List<User> users);

    int deleteById(int uId);

	//Param注解让mapper可以接收多个参数,打破resultType的限制
    int updateById(@Param("uId") int uId, @Param("record") User user);

    String selectPswByUserName(String userName);

    User selectOneByUserName(String userName);

    //获取所有用户信息
    List<User> selectAllUser();
}


UserMapper.xml,增删改查mapper写法,Mybatis插入自增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.ht.test.dao.UserMapper">
    <resultMap id="users" type="com.ht.test.pojo.User">
    	<!-- column对应数据库字段,property对应pojo字段-->
        <id  column="uid" property="uId" javaType="Integer"/>
        <result column="username" property="userName"/>
        <result column="password" property="password"/>
    </resultMap>
    <!-- 查询所有用户信息 -->
    <select id="selectAllUser" resultMap="users">
        select * from User
    </select>
    <select id="selectOneByUserName" parameterType="String" resultMap="users">
        select * from User where userName=#{userName}
    </select>
    <select id="selectPswByUserName" parameterType="String" resultType="String">
        select password from User where userName=#{userName}
    </select>
    <!-- 新增插入用户信息,自增ID方式一: selectKey-->
    <insert id="insert" parameterType="com.ht.test.pojo.User" >
        <selectKey  keyProperty="uId" order="AFTER" resultType="Integer">
            select LAST_INSERT_ID()
        </selectKey>
        insert into user(uid,username,password)
            values(#{uId,jdbcType=INTEGER},
                #{userName,jdbcType=VARCHAR},
                #{password,jdbcType=VARCHAR},
    </insert>
    <!-- 批量新增插入用户信息,自增ID方式二:useGeneratedKeys="true" -->
    <insert id="insertUsers" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="uId" >
        insert into user(uid,username,password)
        values
        <foreach collection="list" item="item" index="index" separator=",">
        (#{item.uId,jdbcType=INTEGER},
        #{item.userName,jdbcType=VARCHAR},
        #{item.password,jdbcType=VARCHAR},
        </foreach>
    </insert>
    <!-- 根据uid删除用户 -->
    <delete id="deleteById" parameterType="Integer" >
        delete from user
        where uid = #{uId,jdbcType=INTEGER}
    </delete>
	<!-- 根据uid更新用户信息,判断传入的字段不为null则更新 -->
    <update id="updateById">
        update user
        <set>
            <if test="record.userName != null">
                username = #{record.userName,jdbcType=VARCHAR},
            </if>
            <if test="record.password != null">
                password = #{record.password,jdbcType=VARCHAR},
            </if>
        </set>
        <if test="uId != null">
            where uid = #{uId,jdbcType=INTEGER}
        </if>
    </update>
</mapper>

~~ ~~

ResultMap的用法

Resultmap可以说是Mybatis中最复杂的元素之一,它描述如何从结果集中加载对象,主要作用是定义映射规则、关联查询、级联的更新、定制类型转化器等。

ResultMap中个参数属性说明

属性 说明
id 结果集的唯一标识,当需要使用此结果集时根据ID进行使用
result 配置Pojo中字段和数据库字段的映射关系
constructor 子元素(idArg 、arg)。可指定使用具体的某个Pojo实体类的构造函数;若Pojo没有无参构造时,也可以用此方法和其他构造函数关联注入字段值。
association 可表示一对一关联关系
collection 可表示一对多关联关系
discriminator 鉴别器,根据指定条件匹配关联指定的Pojo实体类

用上面UserMapper.xml中的配置为例:

<mapper namespace="com.ht.test.dao.UserMapper">
    <resultMap id="users" type="com.ht.test.pojo.User">
        <id property="uId" column="uid" javaType="Integer" jdbcType="INTEGER"/>
        <result column="username" property="userName" javaType="String" jdbcType="VARCHAR"/>
        <result column="password" property="password" javaType="String" jdbcType="VARCHAR"/>
    </resultMap>



ResultMap中子元素id、result中的各个配置参数说明:

属性 说明
column 关联的数据库字段
property 关联的Pojo实体类字段
javaType 数据类型、对应类型的Java完整类名;如果你匹配的是一个JavaBean,那MyBatis 通常会自行检测到。但是如果你想要映射到一个HashMap,需要指定javaType 来达到的目的。
jdbcType 数据库中支持的字段类型
typeHandler 使用这个属性可以覆写类型处理器。这项值可以是一个完整的类名,也可以是一个类型别名。


常见用法

一般返回受影响的条数(基本数据类型),或者某个对象,可以直接使用参数resultType=“Integer”、Pojo类,一般我们都使用Pojo实体类储存查询结果,Mybatis可以自动关联指定的java类。

若这个类没有涉及关联关系,也可以定义resultMap用来明确字段的关系,也建议每个mapper.xml中应当统一去定义结果集,当其他类需要关联查询时才能有结果集可关联。


一对一关联

我们继续使用User类,然后增加一个People类,人员信息和用户名就行成了一对一的关系。使用 association 进行一对一关联的配置。

public class People implements Serializable {
    @ApiModelProperty(value = "人员ID")
    private Integer pId;

    @ApiModelProperty(value = "人员姓名")
    private String pName;

	@ApiModelProperty(value = "身份证号")
    private String idCard;

	@ApiModelProperty(value = "人员的用户信息")
	private User user;
...
构造函数
getter/setter/toString...
}

PeopleMapper.xml

<mapper namespace="com.ht.test.dao.PeopleMapper">
    <resultMap id="peopleMap" type="com.ht.test.pojo.People">
        <id property="pId" column="pid"></id>
        <result property="pName" column="pName"/>
        <result property="idCard" column="idCard"/>
        <result property="address" column="address"/>
        <association property="users" column="username" select="com.ht.test.dao.UserMapper.selectOneByUserName"/>
    </resultMap>

    <select id="selectOnePeopleById" parameterType="Integer" resultMap="People">
        SELECT * FROM People WHERE pid = #{pId}
   </select>
</mapper>

通过关联处理,其中select元素指定的sql查询,而column则是指定传递给select的参数,是user对象的用户名。当取出User的时候,MyBatis就知道下面的sql取出我们需要的级联信息,对应到我们指定的查询方法中去级联查询。

实际上最终执行了两次Sql,一次是People的查询,一次是User的查询。


一对多关联

使用collection进行一对多的关联。对于多对多关联,为了将实现难度降低,一般分解为双方的一对多关系进行配置。

每个用户会存在多个订单的情况,用户和订单就是一对多的关系。新增一个订单实体类。

public class Order implements Serializable {
    @ApiModelProperty(value = "订单id")
    private Integer oId;

    @ApiModelProperty(value = "订单编号")
    private String orderSn;

	@ApiModelProperty(value = "订单总金额")
    private BigDecimal totalAmount;
...
构造函数
getter/setter/toString...

此处用户Pojo中订单list仅作为进行关联的展示,实际情况中一般是在订单中存用户名或者用户ID,再使用用户信息即可查到对应的多张订单。

public class User implements Serializable {
    @ApiModelProperty(value = "用户ID")
    private Integer uId;

    @ApiModelProperty(value = "用户名")
    private String userName;

	@ApiModelProperty(value = "用户的订单")
	priavte List<Order> orders;
...
构造函数
getter/setter/toString...
}
<mapper namespace="com.ht.test.dao.UserMapper">
    <resultMap id="users" type="com.ht.test.pojo.User">
        <id property="uId" column="uid" javaType="Integer"/>
        <result column="username" property="userName"/>
        <result column="password" property="password"/>
        <collection property="users" column="oId" select="com.ht.test.dao.OrderMapper.selectOneOrderById"/>
    </resultMap>

    <select id="selectOneByUserName" parameterType="String" resultMap="users">
        SELECT * FROM User WHERE username = #{userName}
   </select>
</mapper>

经过collection 的关联,当需要查询订单信息时,Mybatis就会根据关联到订单OrserMapper中拿到关联的指定方法查询订单信息。依然是会发出两条sql语句。

collection 也可以直接作为多对多的表示,例如订单和商品,他们是多对多的关系,因此他们会存在中间表(订单详情表),则多对多可以在详情表中进行表示,如下所示。

<mapper namespace="com.ht.test.dao.OrderDetailDao">
    <resultMap id="orderDetailResultMap" type="com.ht.test.dao.OrderDetail">
        <collection property="orderItemList" resultMap="com.ht.test.dao.ItemMapper.ItemMap" columnPrefix="item_"/>
        <collection property="historyList" resultMap="com.ht.test.dao.OrderMapper.OrderMap" columnPrefix="order_"/>
    </resultMap>
</mapper>


鉴别器级联

鉴别器,根据指定条件可以匹配关联指定不同的Pojo实体类。

<resultMap id="orderDetailMapper" type="com.ht.test.dao.OrderDetailDao">
    <discriminator javaType="int" column="types">
        <case value="1" resultMap="ItemMap"></case>
        <case value="2" resultMap="OrderMap"></case>
    </discriminator>
</resultMap>


SpringBoot整合Mybatis难度并不大,跟着以上步骤很快就能整合完成,不过只有学会并且用好了 resultMap 结果集才是用好Mybatis的必经之路,多用多练必不可少。