Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions core/src/main/java/tk/mybatis/mapper/util/OGNL.java
Original file line number Diff line number Diff line change
Expand Up @@ -105,24 +105,39 @@ public static boolean notEmptyCollectionCheck(Object parameter, String error) {
}

/**
* 检查 parameter 对象中指定的 fields 是否全是 null,如果是则抛出异常
* 检查 Example 中是否至少有一个有效的查询条件
* 用于 safeDelete 和 safeUpdate 的安全检查,确保不会执行全表操作
*
* @param parameter
* @return
* @param parameter Example 对象或包含 getOredCriteria 方法的对象
* @return 如果至少有一个有效的查询条件则返回 true
* @throws MapperException 如果参数为 null 或没有有效的查询条件
*/
@SuppressWarnings("unchecked")
public static boolean exampleHasAtLeastOneCriteriaCheck(Object parameter) {
if (parameter != null) {
try {
if (parameter instanceof Example) {
List<Example.Criteria> criteriaList = ((Example) parameter).getOredCriteria();
if (criteriaList != null && criteriaList.size() > 0) {
return true;
for (Example.Criteria criteria : criteriaList) {
if (criteria.isValid()) {
return true;
}
}
}
} else {
Method getter = parameter.getClass().getDeclaredMethod("getOredCriteria");
Object list = getter.invoke(parameter);
if (list != null && list instanceof List && ((List) list).size() > 0) {
return true;
Method isValidGetter = null;
for (Object criteria : (List) list) {
if (isValidGetter == null) {
isValidGetter = criteria.getClass().getDeclaredMethod("isValid");
}
if ((Boolean) isValidGetter.invoke(criteria)) {
return true;
}
}
}
}
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2014-2017 [email protected]
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package tk.mybatis.mapper.test.util;

import org.junit.Test;
import tk.mybatis.mapper.MapperException;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.OGNL;

import jakarta.persistence.Table;

/**
* Test OGNL.exampleHasAtLeastOneCriteriaCheck method
* @author liuzh
*/
public class TestOGNLCriteriaCheck {

// Simple test entity class with table annotation
@Table(name = "test_entity")
static class TestEntity {
private Integer id;
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

/**
* Test with null example - should throw MapperException
*/
@Test(expected = MapperException.class)
public void testNullExample() {
OGNL.exampleHasAtLeastOneCriteriaCheck(null);
}

/**
* Test with empty criteria list - should throw MapperException
*/
@Test(expected = MapperException.class)
public void testEmptyCriteriaList() {
Example example = new Example(TestEntity.class);
OGNL.exampleHasAtLeastOneCriteriaCheck(example);
}

/**
* Test with criteria that has no conditions (invalid) - should throw MapperException
*/
@Test(expected = MapperException.class)
public void testInvalidCriteria() {
Example example = new Example(TestEntity.class);
example.createCriteria(); // Create criteria but don't add any conditions
OGNL.exampleHasAtLeastOneCriteriaCheck(example);
}

/**
* Test with criteria that has null value (invalid) - should throw MapperException
*/
@Test(expected = MapperException.class)
public void testCriteriaWithNullValue() {
Example example = new Example(TestEntity.class);
// When notNull=false (default), null values are ignored and no criteria is added
example.createCriteria().andEqualTo("name", null);
OGNL.exampleHasAtLeastOneCriteriaCheck(example);
}

/**
* Test with multiple criteria where all are invalid - should throw MapperException
*/
@Test(expected = MapperException.class)
public void testMultipleInvalidCriteria() {
Example example = new Example(TestEntity.class);
example.createCriteria().andEqualTo("name", null);
example.or().andEqualTo("name", null);
OGNL.exampleHasAtLeastOneCriteriaCheck(example);
}
}
Comment on lines +38 to +111
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite is missing positive test cases that verify the method returns true when valid criteria exist. Consider adding tests for:

  1. A single criteria with a valid condition (e.g., andEqualTo with a non-null value)
  2. Multiple criteria where at least one is valid (mixed valid/invalid scenario)

These positive tests are important to ensure the fix doesn't break legitimate use cases and properly validates that valid criteria still work as expected.

Copilot uses AI. Check for mistakes.