【MyBatis】MyBatis自動生成コードのクエリ・ピット記

17216 ワード

前言
プロジェクトはSSMフレームを使ってWebバックグラウンドサービスを構築し、フロント後にrestful apiを使用し、バックグラウンドではMyBatis Generatorを使って自動的にコードを生成し、フロントでキーワードを使って検索する時に、いくつかの貴重なピットに遭遇しました.展示に問題があったため、プロジェクトを簡素化しました.
プロジェクトフレーム
バックグラウンドフレーム
バックグラウンドフレームはSpring + SpringMVC + Mybatis + Jettyであり、MyBatisGeneratorを用いてコードを作成し、Jettyは埋め込まれたWebサーバである.
プロジェクトコード
コードはgithubにアップロードされました.
プロジェクト紹介
データ準備
ライブラリssmおよびテーブルusersは、テーブルusersSQLを作成する.

CREATE TABLE `users` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `address` varchar(32) DEFAULT NULL,
  `hobby` varchar(64) DEFAULT NULL,
  `content` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

insert into users(name, address, hobby, content) values("leesf", "hubei", "sport, race", "he is a boy");
insert into users(name, address, hobby, content) values("dyd", "hubei", "painting, reading", "she is a girl");
コードフレームの自動生成
MyBatis Generatorを使って自動的に該当コードを生成します.ソースは以下の通りです.

package com.leesf;

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class MybatisGenerator {
  @Test public void generator() throws Exception {
    List warnings = new ArrayList();
    File configFile = new File(
        "F:/01_Code/01_Idea/ssm-master/src/test/generatorConfig.xml");
    ConfigurationParser cp = new ConfigurationParser(warnings);
    Configuration config = cp.parseConfiguration(configFile);
    DefaultShellCallback callback = new DefaultShellCallback(true);
    MyBatisGenerator myBatisGenerator =
        new MyBatisGenerator(config, callback, warnings);
    myBatisGenerator.generate(null);
  }
}
その中のgeneratoorConfig.xmlファイルは以下の通りです.





    
    
        
            
            
        
        
        
        

        
        
            
        

        
        
            
            
            
            
        

        
        
            
            
        

        
        
            
            
        

        
        

WebServer

WebServer Web , 。


package com.leesf.main;

import java.net.UnknownHostException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class WebServer {
  public static final String CONTEXT = "/";
  private static final Logger LOG = LoggerFactory.getLogger(WebServer.class);
  private static final String DEFAULT_WEBAPP_PATH = "webapps/";
  private Server server;
  private int port;

  public WebServer() {
  }

  public Server createServerInSource() throws UnknownHostException {
    port = 8081;
    server = new Server();
    server.setStopAtShutdown(true);
    SelectChannelConnector connector = new SelectChannelConnector();
    connector.setPort(port);
    connector.setReuseAddress(false);

    connector.setAcceptQueueSize(50);
    connector.setAcceptors(2);
    connector.setThreadPool(
        new ExecutorThreadPool(20,
            40, 0, TimeUnit.SECONDS,
            new ArrayBlockingQueue(
                16, false)));
    connector.setLowResourcesMaxIdleTime(3000);

    connector.setReuseAddress(true);
    connector.setRequestBufferSize(
        16 * 1024);
    connector.setRequestHeaderSize(
        8 * 1024);

    server.setConnectors(new Connector[] { connector });

    String basePath = "src/main/webapps";
    if (StringUtils.isEmpty(basePath)) {
      basePath = DEFAULT_WEBAPP_PATH;
    }
    WebAppContext webContext = new WebAppContext(basePath, CONTEXT);
    webContext.setContextPath(CONTEXT);
    webContext.setDescriptor(basePath + "/WEB-INF/web.xml");
    System.out.println("-------------web.xml path is " + webContext.getDescriptor()
        + "--------------");
    webContext.setResourceBase(basePath);
    webContext.setClassLoader(Thread.currentThread().getContextClassLoader());
    server.setHandler(webContext);
    return server;
  }

  public void start() throws Exception {
    if (server == null) {
      createServerInSource();
    }
    if (server != null) {
      server.start();
      LOG.info("WebServer has started at port:" + port);
    }
  }

  public void stop() throws Exception {
    if (server != null) {
      server.stop();
    }
  }

  public static void main(String[] args) throws Exception {
    WebServer webServer = new WebServer();
    webServer.start();
  }
}

は、イントラブロックJettyを いてWebサービスを し、デモのみを い、パラメータは されていない.ControllerはUserControllerしか しません.ソースは の りです.

package com.leesf.controller;

import com.leesf.po.Users;
import com.leesf.service.UserService;
import com.leesf.utils.ResultUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStreamWriter;
import java.util.List;

@Controller @RequestMapping(value = "/users")
public class UserController {
  @Autowired UserService userService;

  @ResponseBody @RequestMapping(value = "/listUsers", method = {
      RequestMethod.POST, RequestMethod.GET }) public void listUsers(
      HttpServletRequest request, HttpServletResponse response,
      @RequestParam(required = false) String name,
      @RequestParam(required = false) String key) throws Exception {
    System.out.println("xxxxxx");
    OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream());
    List users = userService.getUsers(name, key);
    ResultUtils.resultSuccess(users, out);
  }
}

は、ユーザ とキーワードに づいてユーザを い わせることができる.Service UserServiceImpUserServiceの クラスである.
  • ユーザ クエリによる レコード
  • ソースは の りです
    
    package com.leesf.service.impl;
    
    import com.leesf.mapper.UsersMapper;
    import com.leesf.po.Users;
    import com.leesf.po.UsersExample;
    import com.leesf.service.UserService;
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Service("userService") public class UserServiceImp implements UserService {
      @Autowired UsersMapper usersMapper;
      private Logger LOG = LoggerFactory.getLogger(this.getClass());
    
      public List getUsers(String name, String key) {
        UsersExample usersExample = new UsersExample();
    
        usersExample.createCriteria().andNameLike(name);
    
        List users = usersMapper.selectByExampleWithBLOBs(usersExample);
        return users;
      }
    }
    
    
    
    は、Serviceがマッチングnameの に づいてnameを し、WebServerにアクセスし、コンパイラが している を し、 のようなSQL が されていることを した.urlアクセスの は の りです.
    
    {
        result_code: "0",
        result_msg: "Succeed!",
        result_content: [{
            id: 1,
            name: "leesf",
            address: "hubei",
            hobby: "sport, race",
            content: "he is a boy"
        }]
    }
    
  • は、ユーザ とキーワードクエリに づいて
  • を する.
    
    package com.leesf.service.impl;
    
    import com.leesf.mapper.UsersMapper;
    import com.leesf.po.Users;
    import com.leesf.po.UsersExample;
    import com.leesf.service.UserService;
    import org.apache.commons.lang3.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    @Service("userService") public class UserServiceImp implements UserService {
      @Autowired UsersMapper usersMapper;
      private Logger LOG = LoggerFactory.getLogger(this.getClass());
    
      public List getUsers(String name, String key) {
        UsersExample usersExample = new UsersExample();
    
        if (StringUtils.isNotEmpty(key)) {
          usersExample.or().andAddressLike(key);
          usersExample.or().andHobbyLike(key);
        }
    
        if (StringUtils.isNotEmpty(name)) {
          if (usersExample.getOredCriteria().size() == 0){
            usersExample.createCriteria();
          }
          usersExample.getOredCriteria().get(0).andNameEqualTo(name);
        }
    
        List users = usersMapper.selectByExampleWithBLOBs(usersExample);
        return users;
      }
    }
    
    
    http://localhost:8081/users/listUsers?name=sportのソースコードは、select id, name, address, hobby , content from users WHERE ( name like ? )またはkeyにマッチすることができますが、addressは、nameに する があります.つまり、このようなクエリSQL hobbyを してほしいです.nameを し、select * from users where (address like "%sport%" or hobby like "%sport%") and name = "leesf"にアクセスする.その 、
    
    {
        result_code: "0",
        result_msg: "Succeed!",
        result_content: []
    }
    
    からアクセス のうちWebServerが であることが かります. ログを ると、SQL
    
    select id, name, address, hobby , content from users WHERE ( address like ? and name = ? ) or( hobby like ? ) 
    
    のプログラムが に されているSQLは ったほどではないことが かりました.このとき、MyBatisは にコードを しても http://localhost:8081/users/listUsers?key=sport&name=leesfのようなresult_contentの は、 が です. には のリンクを て、 のように します.
    
      public List getUsers(String name, String key) {
        UsersExample usersExample = new UsersExample();
    
        if (StringUtils.isNotEmpty(key)) {
          usersExample.or().andAddressLike(key);
          usersExample.or().andHobbyLike(key);
        }
    
        if (StringUtils.isNotEmpty(name)){
          if (usersExample.getOredCriteria().size() == 0){
            usersExample.createCriteria();
          }
          usersExample.getOredCriteria().get(0).andNameEqualTo(name);
          usersExample.getOredCriteria().get(1).andNameEqualTo(name);
        }
    
        List users = usersMapper.selectByExampleWithBLOBs(usersExample);
        return users;
      }
    
    この 、 べたら、 が ていないことが かりました. の を べたら、 のように(a or b) and cが つかりました.SQL、 たところ(a or b) and c = (a and c) or (b and c) には がないようですが、 が ないということです.SQLも と じです. いもよらず、 を べても けません. でselect id, name, address, hobby , content from users WHERE ( address like ? and name = ? ) or( hobby like ? and name = ? )SQLを して してみます. のように します.
    
      public List getUsers(String name, String key) {
        UsersExample usersExample = new UsersExample();
    
        if (StringUtils.isNotEmpty(key)) {
          usersExample.or().andAddressLike("%" + key + "%");
          usersExample.or().andHobbyLike("%" + key + "%");
        }
    
        if (StringUtils.isNotEmpty(name)) {
          if (usersExample.getOredCriteria().size() == 0){
            usersExample.createCriteria();
          }
          usersExample.getOredCriteria().get(0).andNameEqualTo(name);
          usersExample.getOredCriteria().get(1).andNameEqualTo(name);
        }
    
        List users = usersMapper.selectByExampleWithBLOBs(usersExample);
        return users;
      }
    
    が を し、urlにアクセスした 、
    
    {
        result_code: "0",
        result_msg: "Succeed!",
        result_content: [{
            id: 1,
            name: "leesf",
            address: "hubei",
            hobby: "sport, race",
            content: "he is a boy"
        }]
    }
    
    
    は or の 、likeは %を しないと になりません.このような で できますが、やや です. にorフィールドが に い 、likeのように がlikeになり、 を き き べます.もっと な き があるかどうかを て、stackoverflowでこのような が されました. のように します.
    
      public List getUsers(String name, String key) {
        UsersExample usersExample = new UsersExample();
    
        if (StringUtils.isNotEmpty(key)) {
          Map maps = new HashMap();
          maps.put("address", key);
          maps.put("hobby", key);
          usersExample.createCriteria().multiColumnOrLike(maps);
        }
    
        if (StringUtils.isNotEmpty(name)) {
          if (usersExample.getOredCriteria().size() == 0){
            usersExample.createCriteria();
          }
          usersExample.getOredCriteria().get(0).andNameEqualTo(name);
        }
    
        List users = usersMapper.selectByExampleWithBLOBs(usersExample);
        return users;
      }
    
    によって、%を した(a or b or c or d) and eは、 の りである.
    
        public static class Criteria extends GeneratedCriteria {
    
            protected Criteria() {
                super();
            }
    
            public Criteria multiColumnOrLike(Map maps) {
                StringBuffer stringBuffer = new StringBuffer();
                stringBuffer.append("( ");
                for (Map.Entry entry : maps.entrySet()) {
                    stringBuffer.append(entry.getKey());
                    stringBuffer.append(" like ");
                    stringBuffer.append("\"%");
                    stringBuffer.append(entry.getValue());
                    stringBuffer.append("%\"");
                    stringBuffer.append(" or ");
                }
    
                int index = stringBuffer.lastIndexOf("or");
                stringBuffer.delete(index, stringBuffer.length());
                stringBuffer.append(")");
                addCriterion(stringBuffer.toString());
                return this;
            }
        }
    
    が を した 、 のようになりました.
    
    {
        result_code: "0",
        result_msg: "Succeed!",
        result_content: [{
            id: 1,
            name: "leesf",
            address: "hubei",
            hobby: "sport, race",
            content: "he is a boy"
        }]
    }
    
    
    まとめでは、MyBatis Generatorを って にコードが されるのを ることができます. のようなピットが れる があります.
  • (a or b)and cクエリーを う 、(a and c)or(b and c) に してクエリーを うことができますが、 にはより い は、Exampleファイルを し、 なクエリー を うことです.
  • でandxLikeを する は「%」を する はなく、(a and e) or (b and e) or (c and e) or (d and e)に する は「%」を しなければなりません.