Scala与MyBatis-Plus动态SQL实操指南

Scala 动态 SQL 实操指南

本文将指导如何在 Scala 项目中实现动态 SQL,重点介绍使用 MyBatis-Plus 实现动态 SQL 的步骤和技巧。

操作前的准备或背景介绍

动态 SQL 在数据库操作中非常常见,允许根据不同条件生成不同的 SQL 语句。在 Scala 项目中,通常使用 MyBatis-Plus 或 JPA 等框架来实现动态 SQL。本指南以 MyBatis-Plus 为例,展示如何在 Scala 中配置和使用动态 SQL。

完成任务所需的详细、分步操作指南

1. 添加依赖

首先需要在 Scala 项目的 build.sbt 文件中添加 MyBatis-Plus 和数据库驱动依赖。

libraryDependencies ++= Seq(
  "com.baomidou" %% "mybatis-plus-boot-starter" % "3.5.3.4",
  "org.springframework.boot" %% "spring-boot-starter-jdbc" % "2.7.4",
  "com.h2database" % "h2" % "2.1.7" // 示例使用 H2 数据库
)

2. 配置 MyBatis-Plus

在 application.yml 文件中配置数据源和 MyBatis-Plus 相关属性。

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password: 
    driver-class-name: org.h2.Driver
  mybatis-plus:
    mapper-locations: classpath:/mapper/*.xml
    type-aliases-package: com.example.demo.model

3. 定义实体类

创建一个简单的实体类,用于映射数据库表。

Scala与MyBatis-Plus动态SQL实操指南

package com.example.demo.model

import com.baomidou.mybatisplus.annotation.TableId
import com.baomidou.mybatisplus.annotation.TableName

@TableName("user")
case class User(
  @TableId val id: Long,
  val name: String,
  val age: Int
)

4. 创建 Mapper 接口

定义一个 Mapper 接口,用于执行动态 SQL。

package com.example.demo.mapper

import com.baomidou.mybatisplus.core.mapper.BaseMapper
import com.example.demo.model.User

trait UserMapper extends BaseMapper[User] {
  def selectByCondition(condition: UserCondition): List[User]
}

case class UserCondition(
  val name: Option[String] = None,
  val ageGreater: Option[Int] = None
)

5. 编写动态 SQL

在 resources/mapper/UserMapper.xml 文件中编写动态 SQL。

<?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.demo.mapper.UserMapper">

  <select id="selectByCondition" resultType="com.example.demo.model.User">
    SELECT id, name, age FROM user
    <where>
      <if test="name != null">name = #{name}</if>
      <if test="ageGreater != null">age > #{ageGreater}</if>
    </where>
  </select>

</mapper>

6. 编写 Service 层

在 Service 层调用 Mapper 接口执行动态 SQL。

package com.example.demo.service

import com.example.demo.mapper.UserMapper
import com.example.demo.model.User
import com.example.demo.model.UserCondition

import scala.jdk.CollectionConverters._

class UserService(val userMapper: UserMapper) {
  def findUsers(condition: UserCondition): List[User] = {
    userMapper.selectByCondition(condition).asScala.toList
  }
}

7. 编写 Controller 层

在 Controller 层提供接口调用 Service 层。

package com.example.demo.controller

import com.example.demo.model.User
import com.example.demo.model.UserCondition
import com.example.demo.service.UserService
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.*

@Tag(name = "User", description = "用户管理")
@RestController
@RequestMapping("/users")
class UserController @Autowired()(userService: UserService) {
  
  @Operation(summary = "根据条件查询用户", responses = Seq(
    ApiResponse(statusCode = 200, description = "查询成功")
  ))
  @GetMapping
  def findUsers(@RequestParam(name = "name", required = false) name: Option[String],
                @RequestParam(name = "ageGreater", required = false) ageGreater: Option[Int]): List[User] = {
    val condition = UserCondition(name, ageGreater)
    userService.findUsers(condition)
  }
}

涉及的关键命令、代码或配置示例

  • 动态 SQL 语法:使用 MyBatis 的 <where> 和 <if> 标签实现条件拼接。
  • 实体类注解:使用 @TableName 和 @TableId 注解映射数据库表和字段。
  • 条件对象:创建条件对象封装查询参数。
  • Mapper 接口:继承 BaseMapper 并定义动态 SQL 方法。

对命令、代码或重要概念的清晰解释

<where> 标签自动处理前导的 “AND” 或 “OR”,避免 SQL 语法错误。<if> 标签根据条件判断是否拼接 SQL片段。

BaseMapper 提供了基础的 CRUD 操作,自定义方法可以灵活扩展动态 SQL 功能。

操作过程中可能遇到的问题、注意事项或相关的实用技巧

  1. SQL 注入风险:确保动态 SQL 使用参数绑定而非字符串拼接。
  2. 性能优化:对于复杂查询,考虑添加索引或使用缓存。
  3. 调试技巧:可以通过 MyBatis-Plus 的日志功能查看生成的 SQL 语句。
  4. 类型转换:Scala 和 Java 类型需要正确映射,避免自动装箱拆箱问题。