forked from mybatis/mybatis-3
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implemented solution suggested by Adam Gent in his blog post: http://…
…adamgent.com/post/30974973820/mybatis-sqlbuilder-rewritten , as he was apparently horrified by the use of ThreadLocal. As explained in the docs, we were aware of the potential for this and the motivations, but there's no reason why we can't offer both.
- Loading branch information
Showing
8 changed files
with
762 additions
and
255 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,293 @@ | ||
/* | ||
* Copyright 2009-2012 The MyBatis Team | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.ibatis.jdbc; | ||
|
||
import java.io.IOException; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public abstract class AbstractSQL<T> { | ||
|
||
private static final String AND = ") \nAND ("; | ||
private static final String OR = ") \nOR ("; | ||
|
||
public abstract T getSelf(); | ||
|
||
public T UPDATE(String table) { | ||
sql().statementType = SQLStatement.StatementType.UPDATE; | ||
sql().tables.add(table); | ||
return getSelf(); | ||
} | ||
|
||
public T SET(String sets) { | ||
sql().sets.add(sets); | ||
return getSelf(); | ||
} | ||
|
||
public T INSERT_INTO(String tableName) { | ||
sql().statementType = SQLStatement.StatementType.INSERT; | ||
sql().tables.add(tableName); | ||
return getSelf(); | ||
} | ||
|
||
public T VALUES(String columns, String values) { | ||
sql().columns.add(columns); | ||
sql().values.add(values); | ||
return getSelf(); | ||
} | ||
|
||
public T SELECT(String columns) { | ||
sql().statementType = SQLStatement.StatementType.SELECT; | ||
sql().select.add(columns); | ||
return getSelf(); | ||
} | ||
|
||
public T SELECT_DISTINCT(String columns) { | ||
sql().distinct = true; | ||
SELECT(columns); | ||
return getSelf(); | ||
} | ||
|
||
public T DELETE_FROM(String table) { | ||
sql().statementType = SQLStatement.StatementType.DELETE; | ||
sql().tables.add(table); | ||
return getSelf(); | ||
} | ||
|
||
public T FROM(String table) { | ||
sql().tables.add(table); | ||
return getSelf(); | ||
} | ||
|
||
public T JOIN(String join) { | ||
sql().join.add(join); | ||
return getSelf(); | ||
} | ||
|
||
public T INNER_JOIN(String join) { | ||
sql().innerJoin.add(join); | ||
return getSelf(); | ||
} | ||
|
||
public T LEFT_OUTER_JOIN(String join) { | ||
sql().leftOuterJoin.add(join); | ||
return getSelf(); | ||
} | ||
|
||
public T RIGHT_OUTER_JOIN(String join) { | ||
sql().rightOuterJoin.add(join); | ||
return getSelf(); | ||
} | ||
|
||
public T OUTER_JOIN(String join) { | ||
sql().outerJoin.add(join); | ||
return getSelf(); | ||
} | ||
|
||
public T WHERE(String conditions) { | ||
sql().where.add(conditions); | ||
sql().lastList = sql().where; | ||
return getSelf(); | ||
} | ||
|
||
public T OR() { | ||
sql().lastList.add(OR); | ||
return getSelf(); | ||
} | ||
|
||
public T AND() { | ||
sql().lastList.add(AND); | ||
return getSelf(); | ||
} | ||
|
||
public T GROUP_BY(String columns) { | ||
sql().groupBy.add(columns); | ||
return getSelf(); | ||
} | ||
|
||
public T HAVING(String conditions) { | ||
sql().having.add(conditions); | ||
sql().lastList = sql().having; | ||
return getSelf(); | ||
} | ||
|
||
public T ORDER_BY(String columns) { | ||
sql().orderBy.add(columns); | ||
return getSelf(); | ||
} | ||
|
||
private SQLStatement sql = new SQLStatement(); | ||
|
||
private SQLStatement sql() { | ||
return sql; | ||
} | ||
|
||
public <A extends Appendable> A usingAppender(A a) { | ||
sql().sql(a); | ||
return a; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
StringBuilder sb = new StringBuilder(); | ||
sql().sql(sb); | ||
return sb.toString(); | ||
} | ||
|
||
private static class SafeAppendable { | ||
private final Appendable a; | ||
private boolean empty = true; | ||
|
||
public SafeAppendable(Appendable a) { | ||
super(); | ||
this.a = a; | ||
} | ||
|
||
public SafeAppendable append(CharSequence s) { | ||
try { | ||
if (empty && s.length() > 0) empty = false; | ||
a.append(s); | ||
} catch (IOException e) { | ||
throw new RuntimeException(e); | ||
} | ||
return this; | ||
} | ||
|
||
public boolean isEmpty() { | ||
return empty; | ||
} | ||
|
||
} | ||
|
||
private static class SQLStatement { | ||
|
||
public enum StatementType { | ||
DELETE, INSERT, SELECT, UPDATE | ||
} | ||
|
||
StatementType statementType; | ||
List<String> sets = new ArrayList<String>(); | ||
List<String> select = new ArrayList<String>(); | ||
List<String> tables = new ArrayList<String>(); | ||
List<String> join = new ArrayList<String>(); | ||
List<String> innerJoin = new ArrayList<String>(); | ||
List<String> outerJoin = new ArrayList<String>(); | ||
List<String> leftOuterJoin = new ArrayList<String>(); | ||
List<String> rightOuterJoin = new ArrayList<String>(); | ||
List<String> where = new ArrayList<String>(); | ||
List<String> having = new ArrayList<String>(); | ||
List<String> groupBy = new ArrayList<String>(); | ||
List<String> orderBy = new ArrayList<String>(); | ||
List<String> lastList = new ArrayList<String>(); | ||
List<String> columns = new ArrayList<String>(); | ||
List<String> values = new ArrayList<String>(); | ||
boolean distinct; | ||
|
||
private void sqlClause(SafeAppendable builder, String keyword, List<String> parts, String open, String close, | ||
String conjunction) { | ||
if (!parts.isEmpty()) { | ||
if (!builder.isEmpty()) | ||
builder.append("\n"); | ||
builder.append(keyword); | ||
builder.append(" "); | ||
builder.append(open); | ||
String last = "________"; | ||
for (int i = 0, n = parts.size(); i < n; i++) { | ||
String part = parts.get(i); | ||
if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND) && !last.equals(OR)) { | ||
builder.append(conjunction); | ||
} | ||
builder.append(part); | ||
last = part; | ||
} | ||
builder.append(close); | ||
} | ||
} | ||
|
||
private String selectSQL(SafeAppendable builder) { | ||
if (distinct) { | ||
sqlClause(builder, "SELECT DISTINCT", select, "", "", ", "); | ||
} else { | ||
sqlClause(builder, "SELECT", select, "", "", ", "); | ||
} | ||
|
||
sqlClause(builder, "FROM", tables, "", "", ", "); | ||
sqlClause(builder, "JOIN", join, "", "", "\nJOIN "); | ||
sqlClause(builder, "INNER JOIN", innerJoin, "", "", "\nINNER JOIN "); | ||
sqlClause(builder, "OUTER JOIN", outerJoin, "", "", "\nOUTER JOIN "); | ||
sqlClause(builder, "LEFT OUTER JOIN", leftOuterJoin, "", "", "\nLEFT OUTER JOIN "); | ||
sqlClause(builder, "RIGHT OUTER JOIN", rightOuterJoin, "", "", "\nRIGHT OUTER JOIN "); | ||
sqlClause(builder, "WHERE", where, "(", ")", " AND "); | ||
sqlClause(builder, "GROUP BY", groupBy, "", "", ", "); | ||
sqlClause(builder, "HAVING", having, "(", ")", " AND "); | ||
sqlClause(builder, "ORDER BY", orderBy, "", "", ", "); | ||
return builder.toString(); | ||
} | ||
|
||
private String insertSQL(SafeAppendable builder) { | ||
sqlClause(builder, "INSERT INTO", tables, "", "", ""); | ||
sqlClause(builder, "", columns, "(", ")", ", "); | ||
sqlClause(builder, "VALUES", values, "(", ")", ", "); | ||
return builder.toString(); | ||
} | ||
|
||
private String deleteSQL(SafeAppendable builder) { | ||
sqlClause(builder, "DELETE FROM", tables, "", "", ""); | ||
sqlClause(builder, "WHERE", where, "(", ")", " AND "); | ||
return builder.toString(); | ||
} | ||
|
||
private String updateSQL(SafeAppendable builder) { | ||
|
||
sqlClause(builder, "UPDATE", tables, "", "", ""); | ||
sqlClause(builder, "SET", sets, "", "", ", "); | ||
sqlClause(builder, "WHERE", where, "(", ")", " AND "); | ||
return builder.toString(); | ||
} | ||
|
||
public String sql(Appendable a) { | ||
SafeAppendable builder = new SafeAppendable(a); | ||
if (statementType == null) { | ||
return null; | ||
} | ||
|
||
String answer; | ||
|
||
switch (statementType) { | ||
case DELETE: | ||
answer = deleteSQL(builder); | ||
break; | ||
|
||
case INSERT: | ||
answer = insertSQL(builder); | ||
break; | ||
|
||
case SELECT: | ||
answer = selectSQL(builder); | ||
break; | ||
|
||
case UPDATE: | ||
answer = updateSQL(builder); | ||
break; | ||
|
||
default: | ||
answer = null; | ||
} | ||
|
||
return answer; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* Copyright 2009-2012 The MyBatis Team | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.apache.ibatis.jdbc; | ||
|
||
public class SQL extends AbstractSQL<SQL> { | ||
|
||
@Override | ||
public SQL getSelf() { | ||
return this; | ||
} | ||
|
||
} |
Oops, something went wrong.