preface
Mybatis (myBatis, mybatis, mybatis, mybatis, mybatis, mybatis, mybatis, mybatis, mybatis)
<if test="type! =null and type ! = "">
and status = 1
</if>
Copy the code
So there is not enough attention paid to this area.
The body of the
The last thing I want to do is write something different, but based on the above, to determine the value of the attribute: Determine the value of the type attribute
<if test="type! =null and type ! = "">
<if test="type=='6'">
and status = 61
</if>
<if test="type! = '6'. "">
and status = 2
</if>
</if>
Copy the code
The result is that no matter what value I pass, status=2 is executed in SQL. I also found a lot of solutions on the Internet, but they are not what I want;
Online solutions
- The double outside the single
<if test='type=="6"'>
and status = 1
</if>
Copy the code
- Gal. ToString ()
<if test="type=='6'.toString()">
and status = 1
</if>
Copy the code
Source code analysis
Mybatis uses ogNL expressions for parsing. The following uses OGNL to simulate parsing; Do not use either of the above methods;
The introduction of pom
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.21.</version>
</dependency>
Copy the code
Test code:
// Build an OgnlContext object
OgnlContext context = (OgnlContext) Ognl.createDefaultContext(this.new DefaultClassResolver(),
new DefaultTypeConverter(),
new DefaultMemberAccess(true));
Map<String,Object> hashMap=new HashMap<>(1);
hashMap.put("name"."aa");
context.setRoot(hashMap);
String expression="name =='aa'";
try {
Boolean flag = (Boolean) Ognl.getValue(expression, context, context.getRoot());
System.out.println(flag);
} catch (OgnlException e) {
e.printStackTrace();
}
Copy the code
Your own solution
In addition to the two ways on the Internet, there are some other ways to solve the problem I encountered;
- Since I am comparing a numeric type, change the value passed in to a numeric type and remove the single quotes from mybatis XML, as follows:
hashMap.put("name".6);
context.setRoot(hashMap);
String expression="name ==6";
Copy the code
Ognl source code parsing
The following is the analysis of the source code of OGNL:
1. Locate the isEqual method of OgnlOps class according to the ogNL. getValue method
public static boolean isEqual(Object object1, Object object2)
{
boolean result = false;
// 1. Check whether the two objects are the same
if (object1 == object2) {
result = true;
} else {
// 2. Set judgment
if((object1 ! =null) && object1.getClass().isArray()) {
if((object2 ! =null) && object2.getClass().isArray() && (object2.getClass() == object1.getClass())) { result = (Array.getLength(object1) == Array.getLength(object2));if (result) {
for(int i = 0, icount = Array.getLength(object1); result && (i < icount); i++) { result = isEqual(Array.get(object1, i), Array.get(object2, i)); }}}}else {
// 3. Non-set judgment
// 3.1 If both values are String, return equals directly. If not, enter compareWithConversion;
// Check for converted equivalence first, then equals() equivalence result = (object1 ! =null) && (object2 ! =null)&& (object1.equals(object2) || (compareWithConversion(object1, object2) == 0)); }}return result;
}
Copy the code
The first value is the value passed in the mybatis method. This value can be of a variety of types, such as BigDecimal, String, Integer, etc. The second value is read from the MYbatis XML file. This value is determined by the way the XML file is written:
- Double single
1.1 When the length is 1, the value is read as Character. 1.2 When the length is greater than 1, the value is read as String
Then locate the compareWithConversion method based on the third judgment
2. CompareWithConversion method
- This method uses getNumericType method to judge the parameter number type. In fact, it can be judged according to the method name. After entering here, it is to judge the number type, then convert, and then compare
- During conversion, if the character passed in cannot be converted, an error will be thrown. For example, if the value passed in is a letter, it cannot be converted.
- If mybatis has an XML file with a judgment value of “” or “”, this method will assign the value to 0;
- When mybatis XML file judgment value is “”, and the value inside is a single value, notice that the converted value is not the original value; For example: ‘6’ resolves to double:54.0
public static int compareWithConversion(Object v1, Object v2)
{
int result;
if (v1 == v2) {
result = 0;
} else {
/ / 1
int t1 = getNumericType(v1), t2 = getNumericType(v2), type = getNumericType(t1, t2, true);
switch(type) {
case BIGINT:
result = bigIntValue(v1).compareTo(bigIntValue(v2));
break;
case BIGDEC:
result = bigDecValue(v1).compareTo(bigDecValue(v2));
break;
case NONNUMERIC:
if ((t1 == NONNUMERIC) && (t2 == NONNUMERIC)) {
if ((v1 instanceof Comparable) && v1.getClass().isAssignableFrom(v2.getClass())) {
result = ((Comparable) v1).compareTo(v2);
break;
} else {
throw new IllegalArgumentException("invalid comparison: " + v1.getClass().getName() + " and "+ v2.getClass().getName()); }}// else fall through
case FLOAT:
case DOUBLE:
// Note that the doubleValue method throws an error when the value passed in is a letter;
double dv1 = doubleValue(v1),
dv2 = doubleValue(v2);
return (dv1 == dv2) ? 0 : ((dv1 < dv2) ? -1 : 1);
default:
long lv1 = longValue(v1),
lv2 = longValue(v2);
return (lv1 == lv2) ? 0 : ((lv1 < lv2) ? -1 : 1); }}return result;
}
Copy the code
conclusion
-
If the property is not of numeric type, using the above online solution will do the job
-
There is a problem if the attribute is of numeric type, such as Integer, BigDecimal, and so on
If the value passed in is 0 and the comparison is “” or “” in the myBatis XML file, the result of the comparison is false, as follows:
// 1 double quote "", pass in a value of 0, or some other value of 0
hashMap.put("name".0);
hashMap.put("name",BigDecimal.ZERO);
String expression="name! =null and name! = \ "\" ";
// 2 Single quotation marks are passed in with a value of 0 or some other type of 0
hashMap.put("name".0);
hashMap.put("name",BigDecimal.ZERO);
String expression="name! =null and name! = "";
Copy the code
The solution:
- Converts the passed value type to String
- In mybatis, modify the XML as follows:
<if test="infSrc ! = null and infSrc! = "">AND INF_SRC = #{infSrc,jdbcType=BIGINT}</if>
/ / or
<if test="infSrc ! = null and infSrc! = "">AND INF_SRC = #{infSrc,jdbcType=DECIMAL}</if>
Copy the code
This depends on the type of value you pass in;
The last
Project address: github.com/guodayede/j…
Refer to the article
- Pit of myBatis’ if test string
- Mybatis if test String comparison does not take effect
- Mandatory object type of OGNL expression in MyBatis