Skip to content

整合MyBatis

在pom.xml引入依赖

xml
        <!--整合Mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <!--需指定版本,2.2.0也可以-->
            <version>2.2.2</version>
        </dependency>

        <!--连接mysql的驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

在application.yaml文件中配置数据库连接

yaml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC
    username: root
    password: yuxingxuan
mybatis:
  # 将目标目录下的bean都设置别名,方便后面在xxxMapper.xml中使用
  type-aliases-package: com.atguigu.boot.pojo
  # 开启驼峰命名规则自动转换
  configuration: # 也可以直接加载全局配置文件——classpath:mybatis-config.xml
    map-underscore-to-camel-case: true

创建User.java

java
package com.atguigu.boot.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;

@AllArgsConstructor
@Data
public class User {
    private Integer id;
    private String name;
    private String password;
}

创建UserDao.java

java
package com.atguigu.boot.Dao;

import com.atguigu.boot.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

@Mapper //给mapper接口自动生成一个实现类,让Spring对mapper接口的bean进行管理,并且可以省略去写复杂的xml文件
public interface UserDao {

    @Select("select * from users where id = #{id}") //IOC容器会自动匹配使用对应的Bean去匹配
    User selectById(@Param("id") Integer id);

    @Update("update users set name = #{name},password = #{password} where id = #{id}")
    int update(User user);
}

通过@Mapper可以让IOC容器获取到Mappre接口的实现类,从而通过自动装配可以直接调用

测试功能

java
    @Resource
    private UserDao userDao;

	@Test
    public void testUserDao(){
        System.out.println(userDao.selectById(2)); //返回查询结果
        System.out.println(userDao.update(new User(2,"jack","123"))); //返回受影响的行数
    }

关于@Mapper和Mapper.xml

  • @Mapper和Mapper.xml两者是可以共存的,但它们不能同时应用于同一个方法上,也就是说,对于同一个方法,只能选择注解方式或XML配置方式之一

  • @Mapper虽然可以简化开发,但是需要使用@Select<script>实现动态sql使用xml的方式可以更为简洁明了的实现动态sql

与UserDao.java同包名(默认开启了同包下匹配),在resources目录下创建UserDao.xml

xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.atguigu.boot.Dao.UserDao">

    <select id="selectById" resultType="User">
        select * from users where id = #{id}
    </select>
</mapper>

对象模型

  • POJO(Plain Old Java Object):最基本的Java对象,是一个简单的、传统的Java对象,不包含任何特定的框架或业务逻辑。POJO通常用来表示数据库中的一条记录,它强调的是简单的属性和getter/setter方法
  • Entity:通常与数据库表一一对应,是JPA(Java Persistence API)中的一个概念,用于持久化到数据库。Entity类通常使用注解来定义映射关系,如@Entity@Table@Column
  • Domain:领域模型,通常指代业务逻辑相关的对象,它不仅包含数据(状态),还包含操作数据的行为(方法)。在DDD(领域驱动设计)中,Domain对象是核心
  • DTO(Data Transfer Object):用于在不同层之间传输数据,尤其是在跨进程或网络调用时。DTO减少了对远程接口的调用次数,它通常包含类的getter/setter方法,没有业务逻辑
  • VO(Value Object):代表数据传输对象的一种形式,通常用于表示UI层需要展示的数据。VO中通常不包含业务逻辑,只是数据的容器
  • BO(Business Object):封装业务逻辑的对象,可以包含多个DTO或Entity。BO主要用于服务层,将业务逻辑封装在一个对象中
  • DO(Data Object):与DTO类似,用于在进程内传递数据,但DO更侧重于数据本身,而不是数据的传输。通常在数据访问层和业务逻辑层之间使用

注解开发

  • @One:用于分步查询,将分步查询的结果映射为一个pojo对象(javaType = User.class)

    • xml
              <!--
                  association:处理多对一的映射关系(处理实体类类型的属性)
                      property:设置需要处理映射关系的属性的属性名
                      javaType:设置要处理的属性的类型
              -->
              <association property="dept" javaType="Dept">
                  <id column="dept_id" property="deptId"></id>
                  <result column="dept_name" property="deptName"></result>
              </association>
  • @Many:用于分步查询,将分步查询的结果保存为集合对象(javaType = List.class)

    • xml
              <!--将查出来的值depy_id作为下一步查询的参数-->
              <collection property="emps"
                          select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpStepTwo"
                          column="dept_id"></collection>
  • 可以手动映射复杂的pojo对象,但是无法直接处理对象中的查询的结果集(orderList),即@Many注解无法使用@Result代替。如果映射对象本身就为结果集(UserAndOrder),就只要将方法的返回结果定义为List即可

    • java
                  // 手动映射复杂对象
                  // id为true表示为主键
                  @Result(id = true, property = "user.id", column = "id"),
                  @Result(property = "user.name", column = "name"),
                  @Result(property = "user.password", column = "password"),

UserAndOrder.java

java
public class UserAndOrder {
    private Integer createUser;
    private User user;
    private List<Order> orderList;
}

Mapper.java

java
    @Select("select id,name,password,create_user FROM tb_users where tb_users.id=#{id}")
    @Results({
            @Result(property = "createUser", column = "create_user"),
            // 手动映射复杂对象
            // id为true表示为主键
//            @Result(id = true, property = "user.id", column = "id"),
//            @Result(property = "user.name", column = "name"),
//            @Result(property = "user.password", column = "password"),

            // 使用分步查询(column代表从数据库提取的字段)
            @Result(property = "user", column = "id",
                    javaType = User.class,
                    one = @One(select = "com.atguigu.boot.Mapper.UserMapper.getUserById")
            ),
            // 映射多个结果集
            @Result(property = "orderList", column = "id",
                    javaType = List.class,
                    many = @Many(select = "com.atguigu.boot.Mapper.UserMapper.getOrderListByUserId")
            )
    })
    UserAndOrder getUserAndOrder(@Param("id") String id);

    @Select("select order_id,user_id,order_name from tb_orders where user_id = #{userId}")
    Order getOrderListByUserId(@Param("userId") String userId);

    @Select("select id,name,password,create_user FROM tb_users where tb_users.id=#{id}")
    User getUserById(@Param("userId") String userId);
==>  Preparing: select id,name,password,create_user FROM tb_users where tb_users.id=?
==> Parameters: 1(String)
<==    Columns: id, name, password, create_user
<==        Row: 1, yuuuuu, 123456, 1
====>  Preparing: select id,name,password,create_user FROM tb_users where tb_users.id=?
====> Parameters: 1(String)
<====    Columns: id, name, password, create_user
<====        Row: 1, yuuuuu, 123456, 1
<====      Total: 1
====>  Preparing: select order_id,user_id,order_name from tb_orders where user_id = ?
====> Parameters: 1(String)
<====    Columns: order_id, user_id, order_name
<====        Row: 1, 1, 测试
<====        Row: 2, 1, 测试1
<====      Total: 2
<==      Total: 1
json
{
    "code": 1,
    "msg": null,
    "data": {
        "createUser": 1,
        "user": {
            "id": 1,
            "name": "yuuuuu",
            "password": "123456"
        },
        "orderList": [
            {
                "orderId": 1,
                "userId": 1,
                "orderName": "测试"
            },
            {
                "orderId": 2,
                "userId": 1,
                "orderName": "测试1"
            }
        ]
    },
    "map": {}
}