真正的Mybatis动态sql—MyBatis Dynamic SQL

·  阅读 1064
真正的Mybatis动态sql—MyBatis Dynamic SQL

MyBatis Dynamic SQL简介

MyBatis缺点

  • MyBatis 为半自动化,需要自己书写sql语句,需要自己定义映射 移值性不好
  • 拼接复杂SQL语句时,没有代码灵活,拼写比较复杂
  • 对开发人员所写的SQL依赖很强
  • 对SQL语句依赖程度很高

MyBatis Dynamic SQL优势

这个库是一个用于生成动态SQL语句的框架。可以将它看作是一个类型安全的sQL模板库,它提供了对MyBatis3和Spring JDBC模板的额外支持。该库将生成供MyBatis或Spring使用的格式化的fuL LETE INET、SELECT和UPDATE语句。最常见的用例是生成可以直接由MyBatis使用的语句和一组数学参数。该库还将生成与Spring JDBC模板兼容的语句和参数对象。该库通过实现一个类似SQL的DSL来工作,该DSL创建一个对象,该对象包含完整的SQL语句和该语句所需的任何参数。

MyBatis Dynamic SQL项目信息

项目地址

github.com/mybatis/myb…

官方文档

mybatis.org/mybatis-dyn…

快速入门

pom.xml文件

       <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>
        <!--mybatis-dynamic-sql-->
        <dependency>
            <groupId>org.mybatis.dynamic-sql</groupId>
            <artifactId>mybatis-dynamic-sql</artifactId>
            <version>1.1.4</version>
        </dependency>
复制代码

快速使用

  • 创建表和列对象
  • 创建映射器(基于XML或Java)
  • 编写和使用SQL出于讨论的目的,我们将展示如何使用库对该表执行CRUD操作: 出于讨论的目的,我们将展示如何使用库对该表执行CRUD操作
create table user (
    id int not null,
    first_name varchar(30) not null,
    create_time TIMESTAMP not null,
    primary key(id)
);
复制代码

创建数据表列对象

package examples.simple.dto;

import java.util.Date;
@Data
public class User {
    private Integer id;
    private String firstName;
    private Date createTime;
}
复制代码

定义常量Tables和Columns

org.mybatis.dynamic.sql.SqlTable表定义包括表的实际名称(包括适当的模式)。如果需要,可以在选择语句中应用表别名。你的Table应该继承SqlTable 类。 org. mybatiss .dynamic.sql. sqlcolumn用于定义在库中使用的列。应该使用SqlTable中的构建器方法创建SqlColumns。列定义包括:

  1. The Java type
  2. The actual column name (an alias can be applied in a select statement)
  3. The JDBC type
  4. (optional) The name of a type handler to use in MyBatis if the default type handler is not desired

我们建议使用以下使用模式以提供最大的灵活性。这个模式允许您以“限定”或“非限定”的方式使用表和列名,这看起来像自然的SQL。例如,在下面的列中,一个列可以被称为firstNameuser.firstName

package examples.simple;

import java.sql.JDBCType;
import java.util.Date;

import org.mybatis.dynamic.sql.SqlColumn;
import org.mybatis.dynamic.sql.SqlTable;

public final class UserSqlSupport {
   public static final User user = new User();
   public static final SqlColumn<Integer> id = user.id;
   public static final SqlColumn<String> firstName= user.firstName;
   public static final SqlColumn<Date> createTime= person.createTime;
   public static final class User extends SqlTable {
       public final SqlColumn<Integer> id = column("id", JDBCType.INTEGER);
       public final SqlColumn<String> firstName= column("first_name", JDBCType.VARCHAR);
       public final SqlColumn<Date> birthDate = column("birth_date", JDBCType.DATE);
       public User() {
           super("User");
       }
   }
}
复制代码

创建 MyBatis3 Mappers

该库将创建用作MyBatis mapper输入的类。这些类包括生成的SQL,以及与生成的SQL匹配的参数集。这两者都是MyBatis所要求的。这些对象应该是MyBatis mapper方法的唯一参数。 (注意:MyBatis Dynamic SQL 不需要XML文件就能工作的很好,但并不意味着不支持XML,毕竟 **MyBatis **最初被设计为是一个 XML 驱动的框架。当你使用关联查询,需要复杂的映射,那么使用XML 与 MyBatis Dynamic SQL 结合起来或者是更好选择,你的XML或许只需要包含一些)

package examples.simple;

import java.util.List;

import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import org.mybatis.dynamic.sql.util.SqlProviderAdapter;

@Mapper
public interface UserMapper {

   @InsertProvider(type=SqlProviderAdapter.class, method="insert")
   int insert(InsertStatementProvider<User> insertStatement);

   @UpdateProvider(type=SqlProviderAdapter.class, method="update")
   int update(UpdateStatementProvider updateStatement);

   @SelectProvider(type=SqlProviderAdapter.class, method="select")
   @Results(id="SimpleTableResult", value= {
           @Result(column="id", property="id", jdbcType=JdbcType.INTEGER, id=true),
           @Result(column="first_name", property="firstName", jdbcType=JdbcType.VARCHAR),
           @Result(column="create_time", property="createTime", jdbcType=JdbcType.DATE),
   })
   List<User> selectMany(SelectStatementProvider selectStatement);

   @SelectProvider(type=SqlProviderAdapter.class, method="select")
   @ResultMap("SimpleTableResult")
   User selectOne(SelectStatementProvider selectStatement);

   @DeleteProvider(type=SqlProviderAdapter.class, method="delete")
   int delete(DeleteStatementProvider deleteStatement);

   @SelectProvider(type=SqlProviderAdapter.class, method="select")
   long count(SelectStatementProvider selectStatement);
}
复制代码

用Mybatis3执行SQL

@Test
void testGeneralSelect() {
   try (SqlSession session = sqlSessionFactory.openSession()) {
       PersonMapper mapper = session.getMapper(PersonMapper.class);

       SelectStatementProvider selectStatement = select(id.as("A_ID"), firstName, crateTime)
       .from(user)
       .where(id, isEqualTo(1))
       .or(firstName, isNull())
       .build()
       .render(RenderingStrategies.MYBATIS3);

       List<User> rows = mapper.selectMany(selectStatement);
       assertThat(rows).hasSize(3);
   }
}

@Test
void testGeneralDelete() {
   try (SqlSession session = sqlSessionFactory.openSession()) {
       UserMapper mapper = session.getMapper(UserMapper.class);

       DeleteStatementProvider deleteStatement = deleteFrom(user)
       .where(occupation, isNull())
       .build()
       .render(RenderingStrategies.MYBATIS3);
       int rows = mapper.delete(deleteStatement);
       assertThat(rows).isEqualTo(2);
   }
}
复制代码

使用mybatis-generator-maven-plugin快速生成代码

pom.xm引入插件

    <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-compiler-plugin</artifactId>
               <version>3.6.0</version>
               <configuration>
                   <source>1.8</source>
                   <target>1.8</target>
                   <encoding>UTF-8</encoding>
               </configuration>
           </plugin>
           <plugin>
               <groupId>org.mybatis.generator</groupId>
               <artifactId>mybatis-generator-maven-plugin</artifactId>
               <version>1.4.0</version>
           </plugin>
       </plugins>
复制代码

配置generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
       PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
       "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
   <!--导入属性配置-->
   <!--mvn自动生成Mapper动态代理
       mvn compile
       mvn mybatis-generator:generate
        -->
   <!--指定特定数据库的jdbc驱动jar包的位置-->
<!--    <classPathEntry location="${db.driverLocation}"/>-->
   <classPathEntry location="C:\Users\1\.m2\repository\mysql\mysql-connector-java\8.0.15\mysql-connector-java-8.0.15.jar"/>
   <context id="default" targetRuntime="MyBatis3DynamicSQL">
       <!-- optional,旨在创建class时,对注释进行控制 -->
       <commentGenerator>
           <property name="suppressDate" value="true"/>
           <property name="suppressAllComments" value="true"/>
       </commentGenerator>

       <!--jdbc的数据库连接 -->
       <jdbcConnection
               driverClass="com.mysql.cj.jdbc.Driver"
               connectionURL="jdbc:mysql://localhost:3306/hotel"
               userId="root"
               password="root">
       </jdbcConnection>


       <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
          NUMERIC 类型解析为java.math.BigDecimal -->
       <javaTypeResolver>
           <property name="forceBigDecimals" value="false"/>
       </javaTypeResolver>

       <!-- Model模型生成器,用来生成含有主键key的类,记录类 以及查询Example类
           targetPackage     指定生成的model生成所在的包名
           targetProject     指定在该项目下所在的路径
       -->
       <javaModelGenerator targetPackage="com.zql.hotel.data.dto" targetProject="../zql-static-data-pojo/src/main/java">
           <!-- 是否允许子包,即targetPackage.schemaName.tableName -->
           <property name="enableSubPackages" value="false"/>
           <!-- 是否对model添加 构造函数 -->
           <property name="constructorBased" value="false"/>
           <!-- 是否对类CHAR类型的列的数据进行trim操作 -->
           <property name="trimStrings" value="true"/>
           <!-- 建立的Model对象是否 不可改变  即生成的Model对象不会有 setter方法,只有构造方法 -->
           <property name="immutable" value="false"/>
       </javaModelGenerator>

       <!-- targetPackage:mapper接口dao生成的位置 -->
       <javaClientGenerator type="XMLMAPPER" targetPackage="com.zql.hotel.data.dao.dynamic" targetProject="../zql-static-data-mapper/src/main/java">
           <!-- enableSubPackages:是否让schema作为包的后缀 -->
           <property name="enableSubPackages" value="true" />
       </javaClientGenerator>
       <!-- geelynote mybatis插件的搭建 -->
       <table tableName="user" domainObjectName="User"/>

   </context>
</generatorConfiguration>
复制代码

最后

后续会持续 Mybatis Dynamic SQL 高级用法,工作原理,源码解析。关注我技术公众号。 Java移动技术栈

分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改