カスタムページング機能インタセプタを実装しながら、springbootはMyBatisの詳細なチュートリアルを統合しました

springboot-MyBatisの基礎となる問合せ

1.データベースを作成します。

実行し、データベースのMySQLの-8.0.11バージョンを使用してCREATE DATABASE 数据库名、テスト用のデータベースを作成し、ここに私が命名TEST_MSした後、我々は、ユーザーがクエリをページングすることにしたいと仮定すると、データテーブルを作成します。

USE TEST_MS;
CREATE TABLE USER(
  ID INT PRIMARY KEY AUTO_INCREMENT,
  USERNAME VARCHAR(30) NOT NULL UNIQUE,
  PASSWORD VARCHAR(100) NOT NULL,
  U_NAME VARCHAR(30) NOT NULL,
  PHONE VARCHAR(11),
  EMAIL VARCHAR(50),
  CITY_ID INT,
  CITY_NAME VARCHAR(15),
  PROVIENCE_ID INT,
  PROVIENCE_NAME VARCHAR(10),
  ADDRESS VARCHAR(30),
  PHOTO VARCHAR(30),
  BIRTHDAY DATE,
  ORGANIZATION_ID INT,
  ROLE_ID INT
);

2.springboot導入MyBatisの

Mavenプロジェクトの導入を作成springbootし、springboot-mybatis依存性を。
pom.xml

	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>
    </dependencies>

ここでは簡略化のため、springbootプロファイルを追加し、接続プールを使用しないでください。
application.yml

server:
    port: 8001
spring:
    application:
      name: user-service
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/TEST_MS?serverTimezone=UTC
        username: 用户名
        password: 密码
mybatis:
  typeAliasesPackage: com.feng.entity
  mapperLocations: classpath:mybatis-mapper/*.xml

前記typeAliasesPackagePOJOマップデータの指定された位置、mapperLocations使用される場合、マッピングファイルマッパDAO層を特定するために、その後、完全な開発モード注釈を省略してもよいです。

3.クエリのマッピングを書きます

POJOは、データのマッピングを作成します。User.java

package com.feng.entity;

import javax.validation.constraints.NotBlank;

/**
 * Created by Feng
 */
public class User {
    private Integer id;
    
	@NotBlank(message = "用户名不能为空")
    private String userName;
    
    @NotBlank(message = "密码不能为空")
    private String passWord;

    private String uName;

    private String phone;

    private String email;

    private String cityID;

    private String cityName;

    private String provienceID;

    private String provienceName;

    private String address;

    private String  organizationID;

    private String roleID;

    private String photo;

    private String birthday;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public String getuName() {
        return uName;
    }

    public void setuName(String uName) {
        this.uName = uName;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getCityID() {
        return cityID;
    }

    public void setCityID(String cityID) {
        this.cityID = cityID;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    public String getProvienceID() {
        return provienceID;
    }

    public void setProvienceID(String provienceID) {
        this.provienceID = provienceID;
    }

    public String getProvienceName() {
        return provienceName;
    }

    public void setProvienceName(String provienceName) {
        this.provienceName = provienceName;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getOrganizationID() {
        return organizationID;
    }

    public void setOrganizationID(String organizationID) {
        this.organizationID = organizationID;
    }

    public String getRoleID() {
        return roleID;
    }

    public void setRoleID(String roleID) {
        this.roleID = roleID;
    }

    public String getPhoto() {
        return photo;
    }

    public void setPhoto(String photo) {
        this.photo = photo;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", passWord='" + passWord + '\'' +
                ", uName='" + uName + '\'' +
                ", phone='" + phone + '\'' +
                ", email='" + email + '\'' +
                ", cityID='" + cityID + '\'' +
                ", cityName='" + cityName + '\'' +
                ", provienceID='" + provienceID + '\'' +
                ", provienceName='" + provienceName + '\'' +
                ", address='" + address + '\'' +
                ", organizationID='" + organizationID + '\'' +
                ", roleID='" + roleID + '\'' +
                ", photo='" + photo + '\'' +
                ", birthday='" + birthday + '\'' +
                '}';
    }
}

クエリを作成UserDaoページングのためのPagerクラスを

package com.feng.dao;

import com.feng.entity.User;
import database.support.Pager;
import org.apache.ibatis.annotations.Param;

import java.util.List;

/**
 * Created by Feng
 */
public interface UserDao {
    List<User> getUser(@Param("user") User user);

    List<User> getUser(@Param("pager") Pager pager, @Param("user") User user);

    User loadUserByUserName(String userName);

    int addUser(User user);

    int addUsers(List<User> userList);
}

package database.support;

import javax.validation.constraints.NotNull;

/**
 * Created by Feng
 */
public class Pager {
    @NotNull
    private int pageNo;

    private int pageSize = 10;

    private int total;

    private String sortBy;

    private String rank = "DESC";

    public int getPageNo() {
        return pageNo;
    }

    public int getPageSize() {
        return pageSize;
    }

    public int getTotal() {
        return total;
    }

    public String getSortBy() {
        return sortBy;
    }

    public String getRank() {
        return rank;
    }

    public Pager setPageNo(int pageNo) throws IllegalAccessException {
        if(pageNo <= 0){
            throw new IllegalAccessException("分页页码必须大于0");
        }
        this.pageNo = pageNo;
        return this;
    }

    public Pager setPageSize(int pageSize) throws IllegalAccessException {
        if(pageSize <= 0){
            throw new IllegalAccessException("单页数据量必须大于0");
        }
        this.pageSize = pageSize;
        return this;
    }

    public Pager setTotal(int total) {
        this.total = total;
        return this;
    }

    public Pager setSortBy(String sortBy) {
        this.sortBy = sortBy;
        return this;
    }

    public Pager setRank(String rank) {
        this.rank = rank;
        return this;
    }
}

私たちは、使用するUserDaoには2ヘビーデューティオフgetUserの一つが唯一のクエリ受け付け、方法User別には、追加取得し、パラメータをPagerページングのためのターゲットを。
これを次に、設定ファイルの春パッケージで指定されたマッピングのために用意されたUserDaoマッピングプロファイルMyBatisののUserMapper.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.feng.dao.UserDao">
    <resultMap id="UserMap" type="com.feng.entity.User">
        <id column="ID" property="id" jdbcType="INTEGER"></id>
        <result column="USERNAME" property="userName" jdbcType="VARCHAR"></result>
        <result column="U_NAME" property="uName" jdbcType="VARCHAR"></result>
        <result column="PHONE" property="phone" jdbcType="VARCHAR"></result>
        <result column="EMAIL" property="email" jdbcType="VARCHAR"></result>
        <result column="CITY_ID" property="cityID" jdbcType="INTEGER"></result>
        <result column="CITY_NAME" property="cityName" jdbcType="INTEGER"></result>
        <result column="PROVIENCE_ID" property="provienceID" jdbcType="INTEGER"></result>
        <result column="PROVIENCE_NAME" property="provienceName" jdbcType="INTEGER"></result>
        <result column="ADDRESS" property="address" jdbcType="INTEGER"></result>
        <result column="PHOTO" property="photo" jdbcType="VARCHAR"></result>
        <result column="BIRTHDAY" property="birthday" jdbcType="DATE"></result>
        <result column="ORGANIZATION_ID" property="organizationID" jdbcType="INTEGER"></result>
        <result column="ROLE_ID" property="roleID" jdbcType="INTEGER"></result>
    </resultMap>
    <sql id="userInfo">
        ID,USERNAME,U_NAME,PHONE,EMAIL,CITY_ID,CITY_NAME,PROVIENCE_ID,PROVIENCE_NAME,ADDRESS,PHOTO,BIRTHDAY,ORGANIZATION_ID,ROLE_ID
    </sql>
    <sql id="cUserInfo">
        <include refid="userInfo"/>,PASSWORD
    </sql>
    <select id="loadUserByUserName" resultMap="UserMap" parameterType="java.lang.String">
        SELECT
        <include refid="cUserInfo"/>
        FROM USER
        WHERE USERNAME = #{userName}
    </select>
    <select id="getUser" resultMap="UserMap" parameterType="com.feng.entity.User">
        SELECT
        <include refid="userInfo"/>
        FROM USER
        <where>
            <if test="user.id != null">
                ID = #{id}
            </if>
            <if test="user.userName != null">
                AND USERNAME = #{userName}
            </if>
            <if test="user.uName != null">
                AND U_NAME LIKE #{uName}
            </if>
            <if test="user.phone != null">
                AND PHONE = #{phone}
            </if>
            <if test="user.email != null">
                AND EMAIL = #{email}
            </if>
            <if test="user.cityID != null">
                AND CITY_ID = #{cityID}
            </if>
            <if test="user.provienceID != null">
                AND PROVIENCE_ID = #{provienceID}
            </if>
            <if test="user.address != null">
                AND ADDRESS LIKE #{address}
            </if>
            <if test="user.organizationID != null">
                AND ORGANIZATION_ID = #{organizationID}
            </if>
            <if test="user.roleID != null">
                AND ROLE_ID = #{roleID}
            </if>
        </where>
    </select>
    <insert id="addUser" parameterType="com.feng.entity.User" >
        insert into USER (ID,USERNAME,PASSWORD,U_NAME,PHONE,EMAIL,CITY_ID,CITY_NAME,PROVIENCE_ID,PROVIENCE_NAME,ADDRESS,PHOTO,BIRTHDAY,ORGANIZATION_ID,ROLE_ID)
        values (#{id},
                #{userName},
                #{passWord},
                #{uName},
                #{phone},
                #{email},
                #{cityID},
                #{cityName},
                #{provienceID},
                #{provienceName},
                #{address},
                #{photo},
                #{birthday},
                #{organizationID},
                #{roleID})
    </insert>
</mapper>

私たちがここにいることに注意すべきUserDao2つの持っているgetUser方法を、だけ設定ファイルにマップするselectラベルを、それはMyBatisのDAOの層との間のマッピング理由であるとにかかわらず、メソッドのパラメータの、唯一のメソッド名に関連します。そのままSQL文のだから、私たちが使用できるパラメータの増加selectマッピング方法に複数のラベルを。唯一の注意点は、複数のオブジェクトパラメータの時にDAO層の操作に渡すことです@Param注釈は、パラメータの名前を指定します。
次に、コンフィギュレーションクラスMyBatisのを追加MybatisConfig

package com.feng.config;

import database.mybatis.plug.PageInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by Feng
 */
@MapperScan("com.feng.dao")
@Configuration
public class MybatisConfig {

}

使用MapperScan場所のDAO層を指定します。
今回はすでに道注入することによって、使用することができUserDao、ユーザデータを照会するために、しかし調整するために、我々は、DAOの上に層を追加service層、書き込みUserServiceインターフェースと実装クラスを

package com.feng.service;

import com.feng.entity.User;
import database.support.Pager;

import java.util.List;

/**
 * Created by Feng
 */
public interface UserService {
    public User getUserByID(int id);

    public int removeUserByID(int id);

    public User loadUserByUserName(String userName);

    public List<User> getUser(Pager pager,User user);

    public List<User> getUser(User user);

}

package com.feng.service;

import com.feng.dao.UserDao;
import com.feng.entity.User;
import database.support.Pager;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * Created by Feng
 */
@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserDao userDao;

    @Override
    public User getUserByID(int id) {
        User queryUser = new User();
        queryUser.setId(id);
        List<User> users = userDao.getUser(queryUser);
        if(users != null && users.size() > 0){
            return users.get(0);
        }
        return null;
    }

    @Override
    public int removeUserByID(int id) {
        return 0;
    }

    @Override
    public User loadUserByUserName(String userName) {
        return userDao.loadUserByUserName(userName);
    }

    @Override
    public List<User> getUser(Pager pager, User user) {
        return userDao.getUser(pager,user);
    }

    @Override
    public List<User> getUser(User user) {
        return userDao.getUser(user);
    }
}

起動クラスとJUnitテストクラスを作成します。

package com.feng;

import org.springframework.boot.SpringApplication;

@SpringBootApplication
public class SpringBootWebApplication {
    public static void main(String[] args){
        SpringApplication.run(SpringBootWebApplication.class, args);
    }
}

import com.feng.SpringBootWebApplication;
import com.feng.entity.User;
import com.feng.service.UserService;
import database.support.Pager;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

/**
 * Created by Feng
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = SpringBootWebApplication.class)
public class JDBCTest {
    @Autowired
    private UserService userService;

    @Test
    public void testQuery() throws IllegalAccessException {
        List<User> users = userService.getUser(new User());
        System.out.println(users);
    }
}

一般的なクエリのテストに成功
ここに画像を挿入説明

4.カスタムインターセプタタブ

三つの方法MyBatisのページングはほとんどまだインターセプタのページングを使用して、実際の生産では、ナンセンス、基本的にはほとんど役に立ちませんメモリまたはページングのSQLステートメントではありません。私は、インターネット上で中国の関連情報は、九十%がpageHelperプラグで直接実行されている見つけます。彼が、プラグインのチュートリアルの多くを書いた理由は人によって書かれたので、総合的な中国の文書、文書に直接スキップは大丈夫ではないことを不可解されます。
自宅に近い、ここに自動的に含まれているブロックするために私たち自身のインターセプター(プラグイン)を書き込むためのPagerクエリメソッドのパラメータが
見える公式文書をインターセプタの記述に

プラグイン(プラグイン)
MyBatisのマッピングプロセスは、あなたが呼び出しをインターセプトするポイントのステートメントの実行を持つことができます。デフォルトでは、MyBatisのメソッドが呼び出しには、インターセプトするプラグインを使用することができます:
キュータ(更新、クエリ、flushStatements、コミット、ROLLBACK、getTransaction、閉じる、閉じられ使用)
ParameterHandler(getParameterObject、setParametersを使用)を
ResultSetHandler(handleResultSets、handleOutputParameters)
StatementHandler(パラメータ化するために、PREPARE 、バッチ、更新、照会)
方法のこれらのクラスの詳細は、直接ソースコードを表示し、各メソッドのシグネチャまたは配布パッケージMyBatisのを見ることによって見出すことができます。あなただけの監視方法を呼び出す以上のことをやりたい場合は、より良いかなりメソッドの動作を理解して書き換えることと思います。変更または行動の既存のメソッドをオーバーライドしようとした場合ので、あなたはMyBatisのコアモジュールを損なう可能性があります。これらは、低レベルのクラスおよびメソッドは、プラグインの使用は、非常に注意してください。
MyBatisのプラグインを使用して、強力なメカニズムは非常に簡単です提供し、ちょうどインターセプタを実装し、ブロックするためのメソッドシグネチャを指定します。

役割これらのオブジェクトとその内部の方法として、あなたは、オンラインの関連情報を見つけることができ、我々はそのブロックしたいStatementHandler.prepare文を生成するために使用される方法を、パラメータが含まれConnectionたオブジェクトを照会が起動する前に、私たちは、最初に実行するためにそれを使用することができますカウント動作をして、元のSQL文を置き換える
ユーティリティSQL文のページを構築するために使用されるクラスとカウントを書くために

package database.support;

/**
 * Created by Feng
 */
public interface JDBCSupport {
    public String generatePageSql(Pager pager,String sql);

    public String generateCountSql(String sql);
}

package database.support;

import org.springframework.util.StringUtils;

/**
 * Created by Feng
 */
public class MySqlSupport implements JDBCSupport {
    /**
     * 拼接分页sql
     * @param pager
     * @param sql
     * @return
     */
    @Override
    public String generatePageSql(Pager pager, String sql) {
        long startIndex = (pager.getPageNo() - 1) * pager.getPageSize()+1;
        long endIndex = startIndex + pager.getPageSize()-1;
        StringBuilder sqlBuilder = new StringBuilder(sql);

        if(!StringUtils.isEmpty(pager.getSortBy())){
            sqlBuilder.append(" ORDER BY ");
            sqlBuilder.append(pager.getSortBy());
            sqlBuilder.append(pager.getRank());
        }
        sqlBuilder.append(" limit ");
        sqlBuilder.append(startIndex);
        sqlBuilder.append(",");
        sqlBuilder.append(endIndex);
        return sqlBuilder.toString().toUpperCase();
    }

    /**
     * 拼接计数sql
     * @param sql
     * @return
     */
    @Override
    public String generateCountSql(String sql) {
        return ("SELECT COUNT(*) FROM (" + sql + ") A").toUpperCase();
    }

}

次のステップは、最も重要なインターセプターです

package database.mybatis.plug;

import database.support.JDBCSupport;
import database.support.MySqlSupport;
import database.support.Pager;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Map;
import java.util.Properties;

/**
 * Created by Feng
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class,Integer.class}),
})
public class PageInterceptor implements Interceptor {
    private JDBCSupport jdbcSupport = new MySqlSupport();

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler)invocation.getTarget();
        Map<String,Object> paramsMap = (Map<String, Object>) statementHandler.getParameterHandler().getParameterObject();

        String sql = statementHandler.getBoundSql().getSql();
        for(String key:paramsMap.keySet()){
            if(paramsMap.get(key) instanceof Pager){
                Pager pager = (Pager) paramsMap.get(key);
                Connection connection = (Connection)invocation.getArgs()[0];
                PreparedStatement countStatement = connection.prepareStatement(jdbcSupport.generateCountSql(sql));
                ResultSet rs = countStatement.executeQuery();
                if(rs.next()) {
                    pager.setTotal(rs.getInt(1));
                }
                MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
                String pageSql = jdbcSupport.generatePageSql(pager,sql);
                metaObject.setValue("delegate.boundSql.sql", pageSql);
                break;
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object o) {
        if (o instanceof StatementHandler) {
            return Plugin.wrap(o, this);
        } else {
            return o;
        }
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

Interceptsインターセプタ機能を識別するためのターゲットとターゲット注釈方法。ではinterceptこの方法は、まず、すべての測定パラメータと横断方法を得る、そして時に含有していることが分かっPagercountパラメータは、我々は最初のクエリ文が実行され、結果が書かれて構築Pagerした後、構築、SQLタブ反射ツールを意味し置き換えるためにMyBatisのが来ますクエリ。
前のクラスコンフィギュレーションMyBatisの中で、このインターセプタを追加

package com.feng.config;

import database.mybatis.plug.PageInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by Feng
 */
@MapperScan("com.feng.dao")
@Configuration
public class MybatisConfig {
    /**
     * 添加mybatis分页拦截器
     * @return
     */
    @Bean
    public PageInterceptor pageInterceptor(){
        return new PageInterceptor();
    }

}

新しい試験方法

@Test
    public void testPagerQuery() throws IllegalAccessException {
        Pager pager = new Pager().setPageSize(2).setPageNo(1);
        List<User> users = userService.getUser(pager,new User());
        System.out.println(users);
        System.out.println(pager);
    }

テスト結果
ここに画像を挿入説明

おすすめ

転載: blog.csdn.net/qq_35488769/article/details/90671948