【MyBatis】MyBatis自動生成コードのクエリ・ピット記
17216 ワード
前言
プロジェクトはSSMフレームを使ってWebバックグラウンドサービスを構築し、フロント後に
プロジェクトフレーム
バックグラウンドフレーム
バックグラウンドフレームは
プロジェクトコード
コードはgithubにアップロードされました.
プロジェクト紹介
データ準備
ライブラリ
MyBatis Generatorを使って自動的に該当コードを生成します.ソースは以下の通りです.
プロジェクトはSSMフレームを使ってWebバックグラウンドサービスを構築し、フロント後に
restful api
を使用し、バックグラウンドではMyBatis Generatorを使って自動的にコードを生成し、フロントでキーワードを使って検索する時に、いくつかの貴重なピットに遭遇しました.展示に問題があったため、プロジェクトを簡素化しました.プロジェクトフレーム
バックグラウンドフレーム
バックグラウンドフレームは
Spring + SpringMVC + Mybatis + Jetty
であり、MyBatisGenerator
を用いてコードを作成し、Jetty
は埋め込まれたWebサーバである.プロジェクトコード
コードはgithubにアップロードされました.
プロジェクト紹介
データ準備
ライブラリ
ssm
およびテーブルusers
は、テーブルusers
のSQL
を作成する.
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 UserServiceImp
はUserService
の クラスである.ユーザ クエリによる レコード ソースは の りです
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)
に する は「%」を しなければなりません.