add method parse

This commit is contained in:
Shaun Chyxion 2017-10-05 11:55:07 +08:00
parent c8ceb34c62
commit 69b738a9a1
10 changed files with 449 additions and 10 deletions

@ -1 +0,0 @@
Subproject commit a7c690619e09fae1d48584794d68d1b8ee78c197

@ -1 +0,0 @@
Subproject commit a7c690619e09fae1d48584794d68d1b8ee78c197

View File

@ -38,7 +38,13 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
<version>1.13.1.RELEASE</version>
<version>2.0.0.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<!-- /MyBatis -->
<dependency>

View File

@ -2,15 +2,19 @@ package me.chyxion.tigon.mybatis.test;
import lombok.extern.slf4j.Slf4j;
import me.chyxion.tigon.mybatis.test.model.Activity;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.repository.query.parser.Part;
import static org.springframework.data.repository.query.parser.Part.Type.*;
import org.springframework.data.repository.query.parser.PartTree;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.*;
import org.xml.sax.helpers.DefaultHandler;
import me.chyxion.tigon.mybatis.BaseMapper;
import org.apache.ibatis.parsing.XPathParser;
@ -82,15 +86,273 @@ public class TestDriver {
@Test
public void testParse() {
PartTree tree = new PartTree("findByIdAndHoldingDateOrderById", Activity.class);
final PartTree tree = new PartTree("findByIdLessThanAndIdStartsWithAndIdInAndIdNotInOrIdAndHoldingDateOrIdBetweenOrderById", Activity.class);
final Iterator<PartTree.OrPart> itOrParts = tree.iterator();
List<StringBuilder> sqlFrags = new LinkedList<StringBuilder>();
int paramIndex = 0;
while (itOrParts.hasNext()) {
final PartTree.OrPart orPart = itOrParts.next();
log.info("Or part [{}] found.", orPart);
final Iterator<Part> itOrPart = orPart.iterator();
List<String> andParts = new LinkedList<String>();
int orPartIndex = 0;
while (itOrPart.hasNext()) {
final Part part = itOrPart.next();
final PropertyPath prop = part.getProperty();
final Part.Type type = part.getType();
final int numArgs = part.getNumberOfArguments();
andParts.add(buildSQL(part, paramIndex, orPartIndex == 0));
log.info("Part [{}], path [{}], number of arg [{}], type [{}].", part, prop.toDotPath(), numArgs, type.name());
paramIndex += numArgs;
++orPartIndex;
}
log.info("[{}] and parts found.", andParts.size());
sqlFrags.add(new StringBuilder(StringUtils.join(andParts, " ")));
}
log.info("SQL [{}].", StringUtils.join(sqlFrags, " "));
final Sort sort = tree.getSort();
if (sort != null) {
Iterator<Sort.Order> itSort = sort.iterator();
while (itSort.hasNext()) {
Sort.Order order = itSort.next();
log.info("Order [{}] [{}]", order.getProperty(), order.getDirection());
}
}
}
private String buildSQL(Part part, final int paramIndex, boolean orClause) {
final PropertyPath prop = part.getProperty();
final Part.Type type = part.getType();
final String col = prop.toDotPath();
if (BETWEEN.equals(type)) {
//
return col + " between #{param" + paramIndex + "} and #{param" + (paramIndex + 1) + "}";
}
else if (CONTAINING.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " like #{param" + paramIndex + "}");
}
else if (ENDING_WITH.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " like #{param" + paramIndex + "}");
}
else if (FALSE.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, false, col + " is false");
}
else if (GREATER_THAN.equals(type) || AFTER.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " > #{param" + paramIndex + "}");
}
else if (GREATER_THAN_EQUAL.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " >= #{param" + paramIndex + "}");
}
else if (IN.equals(type)) {
return ifNotNullTag(paramIndex, true, orClause, true, col + " in " + buildArray(paramIndex));
}
else if (IS_NOT_NULL.equals(type) || EXISTS.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, false, col + " is not null");
}
else if (IS_NULL.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, false, col + " is null");
}
else if (LESS_THAN.equals(type) || BEFORE.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " < #{param" + paramIndex + "}");
}
else if (LESS_THAN_EQUAL.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " <= #{param" + paramIndex + "}");
}
else if (LIKE.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " like #{param" + paramIndex + "}");
}
else if (NEGATING_SIMPLE_PROPERTY.equals(type)) {
return col + " <> #{param" + paramIndex + "}";
}
else if (NOT_IN.equals(type)) {
return ifNotNullTag(paramIndex, true, orClause, true, col + " not in " + buildArray(paramIndex));
}
else if (NOT_LIKE.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " not like #{param" + paramIndex + "}");
}
else if (REGEX.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " regexp #{param" + paramIndex + "}");
}
else if (SIMPLE_PROPERTY.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true, col + " = #{param" + paramIndex + "}");
}
else if (STARTING_WITH.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, true,
bindTag("param" + paramIndex + "_var", "param" + paramIndex + " + '%'") +
col + " like #{param" + paramIndex + "_var}");
}
else if (TRUE.equals(type)) {
return ifNotNullTag(paramIndex, false, orClause, false, col + " is true");
}
else if (NOT_CONTAINING.equals(type)) {
// TODO
return col + " not like #{param" + paramIndex + "}";
}
// redis
else if (NEAR.equals(type)) {
}
// redis
else if (WITHIN.equals(type)) {
return col + " like #{param" + paramIndex + "}";
}
return null;
}
String ifNotNullTag(int paramIndex, boolean collection, boolean orClause, boolean wrapIf, String sql) {
if (wrapIf) {
return ifNotNullTag(paramIndex, collection, orClause, sql);
}
return (orClause ? " or " : " and ") + sql;
}
String bindTag(final String name, final String value) {
return "<bind name=\"" + name + "\" value=\"" + value + "\" />";
}
String buildArray(int paramIndex) {
return new StringBuilder("<foreach collection=\"")
.append("param")
.append(paramIndex)
.append("\" item=\"__val__\" open=\"(\" separator=\", \" close=\")\">\n")
.append("#{__val__}")
.append("</foreach>\n")
.toString();
}
String ifNotNullTag(int paramIndex, boolean orClause, String innerTag) {
return new StringBuilder("<if test=\"").append("param")
.append(paramIndex)
.append(" != null\">\n")
.append(orClause ? " or " : " and ")
.append(innerTag)
.append("</if>\n")
.toString();
}
String ifNotEmptyTag(int paramIndex, boolean orClause, String innerTag) {
return new StringBuilder("<if test=\"")
.append("param")
.append(paramIndex)
.append(" != null and ((")
.append("param")
.append(paramIndex)
.append(".getClass().isArray() and ")
.append("param")
.append(paramIndex)
.append(".length")
.append(") or (")
.append("param")
.append(paramIndex)
.append(" instanceof java.lang.Iterable and ")
.append("param")
.append(paramIndex)
.append(".iterator().hasNext()")
.append("))\">\n")
.append(orClause ? " or " : " and ")
.append(innerTag)
.append("</if>\n")
.toString();
}
String ifNotNullTag(int paramIndex, boolean collection, boolean orClause, String innerTag) {
StringBuilder sbRtn = new StringBuilder("<if test=\"");
if (collection) {
sbRtn.append("param")
.append(paramIndex)
.append(" != null and ((")
.append("param")
.append(paramIndex)
.append(".getClass().isArray() and ")
.append("param")
.append(paramIndex)
.append(".length")
.append(") or (")
.append("param")
.append(paramIndex)
.append(" instanceof java.lang.Iterable and ")
.append("param")
.append(paramIndex)
.append(".iterator().hasNext()")
.append("))\">\n");
}
else {
sbRtn.append("param")
.append(paramIndex)
.append(" != null\">\n");
}
return sbRtn.append(orClause ? " or " : " and ")
.append(innerTag)
.append("</if>\n").toString();
}
String ifNotNullTag(int paramIndex, boolean collection, boolean orClause, InnerTag innerTag) {
StringBuilder sbRtn = new StringBuilder("<if test=\"");
if (collection) {
sbRtn.append("param")
.append(paramIndex)
.append(" != null and ((")
.append("param")
.append(paramIndex)
.append(".getClass().isArray() and ")
.append("param")
.append(paramIndex)
.append(".length")
.append(") or (")
.append("param")
.append(paramIndex)
.append(" instanceof java.lang.Iterable and ")
.append("param")
.append(paramIndex)
.append(".iterator().hasNext()")
.append("))\">\n");
}
else {
sbRtn.append("param")
.append(paramIndex)
.append(" != null\">\n");
}
return sbRtn.append(orClause ? " or " : " and ")
.append(innerTag.tag())
.append("</if>\n").toString();
}
interface InnerTag {
String tag();
}
@Test
public void testParse1() {
PartTree tree = new PartTree("findIdById", Activity.class);
log.info("tree to string: [{}].", tree);
Iterator<PartTree.OrPart> iterator = tree.iterator();
while (iterator.hasNext()) {
log.info("OrPart [{}].", iterator.next());
PartTree.OrPart next = iterator.next();
log.info("OrPart [{}].", next);
Iterator<Part> iterator1 = next.iterator();
while (iterator1.hasNext()) {
Part next1 = iterator1.next();
PropertyPath property = next1.getProperty();
Part.Type type = next1.getType();
Collection<String> keywords = type.getKeywords();
log.info("Part [{}], path [{}], number of arg [{}], type [{}].", next1, property.toDotPath(), next1.getNumberOfArguments(), type.name());
}
}
log.info("join or part [{}].", StringUtils.join(tree.iterator(), " or "));
System.err.println("");
for (Part part : tree.getParts()) {
System.err.println(part);
}
System.err.println(tree);
// System.err.println(tree);
// Iterator<Sort.Order> iterator1 = tree.getSort().iterator();
// while (iterator1.hasNext()) {
// System.err.println(iterator1.next());
// }
// tree = new PartTree("listByIdOrLastName", Customer.class);
// System.err.println(tree);
}

View File

@ -0,0 +1,52 @@
package me.chyxion.tigon.mybatis.test;
import me.chyxion.tigon.mybatis.test.mapper.UserMapper;
import me.chyxion.tigon.mybatis.test.model.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.lang.reflect.Method;
import java.util.List;
/**
* @version 0.0.1
* @since 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* May 17, 2016 9:54:18 AM
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring/spring-*.xml")
public class UserMapperTest {
@Autowired
private UserMapper mapper;
@Test
public void testList() {
List<User> list = mapper.list(null);
System.err.println(list);
}
@Test
public void testListByGender() {
List<User> list = mapper.findByGender("M");
System.err.println(list);
}
@Test
public void testGetAllMethod() {
Method[] declaredMethods = UserMapper.class.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.err.println("Declared Method: " + declaredMethod.getName());
}
for (Method declaredMethod : UserMapper.class.getMethods()) {
System.err.println("Method: " + declaredMethod.getName());
}
}
}

View File

@ -1,5 +1,6 @@
package me.chyxion.tigon.mybatis.test.mapper;
import java.util.Date;
import me.chyxion.tigon.mybatis.BaseMapper;
import me.chyxion.tigon.mybatis.test.model.Activity;
@ -11,4 +12,5 @@ import me.chyxion.tigon.mybatis.test.model.Activity;
* May 17, 2016 9:54:18 AM
*/
public interface ActivityMapper extends BaseMapper<Long, Activity> {
Activity findByIdAndHoldingDateOrderById(Long id, Date holdingDate);
}

View File

@ -0,0 +1,24 @@
package me.chyxion.tigon.mybatis.test.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import me.chyxion.tigon.mybatis.BaseMapper;
import me.chyxion.tigon.mybatis.test.model.User;
import org.hibernate.validator.constraints.NotBlank;
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Jun 7, 2017 8:55:14 PM
*/
public interface UserMapper extends BaseMapper<String, User> {
List<User> listByCustomerId(
@NotBlank
@Param("customerId")
String customerId);
List<User> findByGender(String gender);
}

View File

@ -0,0 +1,50 @@
package me.chyxion.tigon.mybatis.test.model;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Getter;
import lombok.Setter;
import me.chyxion.tigon.model.M3;
import me.chyxion.tigon.mybatis.NotUpdate;
import me.chyxion.tigon.mybatis.NotUpdateWhenNull;
import me.chyxion.tigon.mybatis.Table;
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Jun 7, 2017 8:43:52 PM
*/
@Getter
@Setter
@Table("crm_user")
public class User extends M3<String, String> {
private static final long serialVersionUID = 1L;
// roles
public static final String ROLE_ADMIN = "ADMIN";
// Column Names
public static final String ACCOUNT = "account";
public static final String EMPLOYEE_ID = "employee_id";
public static final String PASSWORD = "password";
public static final String MOBILE = "mobile";
public static final String EMAIL = "email";
public static final String NAME = "name";
public static final String EN_NAME = "en_name";
public static final String GENDER = "gender";
public static final String ADMIN = "admin";
// Properties
private String account;
@NotUpdate
private String employeeId;
@NotUpdateWhenNull
@JSONField(serialize = false)
private String password;
private String mobile;
private String email;
private String name;
private String enName;
private String gender;
private boolean admin;
}

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* @version 0.0.1
* @author Auto Generated <br>
* Tech Support <a href="mailto:chyxion@163.com">Shaun Chyxion</a><br>
* Jun 7, 2017 8:55:14 PM
*/
-->
<!DOCTYPE mapper PUBLIC
"-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="me.chyxion.tigon.mybatis.test.mapper.UserMapper">
<select id="listByCustomerId" resultType="me.chyxion.tigon.mybatis.test.model.User">
select u.id,
u.employee_id,
u.account,
u.name,
u.en_name,
u.gender,
u.mobile,
u.email,
u.password,
u.admin,
u.enabled,
u.note,
u.updated_by,
u.date_updated,
u.date_created,
u.created_by
from <include refid="table" /> u
join crm_customer_permission perm
on u.account = perm.user_account
where u.enabled = 1
and perm.enabled = 1
and perm.customer_id = #{customerId}
</select>
<select id="findByGender" resultType="me.chyxion.tigon.mybatis.test.model.User">
select <include refid="cols" />
from <include refid="table" />
where gender = #{param1}
</select>
</mapper>

View File

@ -1,9 +1,9 @@
# Config Dev
# Database
db.url=jdbc:mysql://127.0.0.1:3306/summer_mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
db.url=jdbc:mysql://127.0.0.1:43306/ambition_crm?useUnicode=true&characterEncoding=utf-8&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
db.user=root
db.password=12345678
db.password=696@2^~)oZ@^#*Q
redis.host=127.0.0.1
redis.password=0211