Skip to content

Conversation

@ajie-dev
Copy link
Contributor

No description provided.

@ajie-dev
Copy link
Contributor Author

示例

image

@liukai237
Copy link

貌似没有处理逻辑删除

@abel533 abel533 added the jdk8 label Oct 16, 2022
@abel533
Copy link
Owner

abel533 commented Oct 16, 2022

升级jdk8时合并。

@abel533 abel533 requested a review from Copilot February 11, 2026 09:03
@abel533 abel533 merged commit 6493164 into abel533:master Feb 11, 2026
4 checks passed
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an “additional select” mapper/provider to query entities by non-null fields in a record parameter while allowing callers to specify which columns/properties to return.

Changes:

  • Introduces SelectSpecifyColumnsMapper with methods to select by explicit column names or by entity properties (Fn).
  • Adds SelectSpecifyColumnsProvider to generate dynamic SELECT SQL with a <foreach> column list and record-based WHERE conditions.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.

File Description
extra/src/main/java/tk/mybatis/mapper/additional/select/SelectSpecifyColumnsProvider.java Builds dynamic SELECT SQL for “specified columns/properties” queries and constructs a record-based WHERE clause.
extra/src/main/java/tk/mybatis/mapper/additional/select/SelectSpecifyColumnsMapper.java Exposes new mapper methods to query with specified return columns/properties.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +30 to +33
sql.append("SELECT ");
sql.append("<foreach collection=\"columns\" item=\"item\" open=\"\" separator=\",\" close=\"\">");
sql.append("${item}");
sql.append("</foreach>");
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

selectByColumns directly interpolates user-provided columns via ${item}. This is raw string substitution and allows SQL injection (e.g., id, (select ...)), and also bypasses any column-name quoting rules. Consider mapping requested names to an allow-list derived from EntityHelper.getColumns(entityClass) (or only accepting Fn<T, ?> like selectByPropertys) and fail fast when an unknown column is requested.

Copilot uses AI. Check for mistakes.
Comment on lines +64 to +86
public static String whereAllIfColumns(Class<?> entityClass, boolean empty, boolean useVersion) {
StringBuilder sql = new StringBuilder();
sql.append("<where>");
Set<EntityColumn> columnSet = EntityHelper.getColumns(entityClass);
Iterator var5 = columnSet.iterator();

while (true) {
EntityColumn column;
do {
if (!var5.hasNext()) {
if (useVersion) {
sql.append(SqlHelper.whereVersion(entityClass));
}

sql.append("</where>");
return sql.toString();
}

column = (EntityColumn) var5.next();
} while (useVersion && column.getEntityField().isAnnotationPresent(Version.class));

sql.append(getIfNotNull(column, " AND " + getColumnEqualsHolder(column), empty));
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

This provider reimplements SqlHelper.whereAllIfColumns but omits the logic-delete predicate that the core helper adds. For entities with a logic-delete column, this will return logically deleted rows. Align with core behavior by detecting the logic-delete column and appending SqlHelper.whereLogicDelete(entityClass, false) inside the <where> block (similar to core/.../SqlHelper.whereAllIfColumns).

Copilot uses AI. Check for mistakes.
Comment on lines +90 to +132
StringBuilder sql = new StringBuilder();
sql.append("<if test=\"");

sql.append("record.").append(column.getProperty()).append(" != null");
if (empty && column.getJavaType().equals(String.class)) {
sql.append(" and ").append(column.getProperty()).append(" != '' ");
}

sql.append("\">");
sql.append(contents);
sql.append("</if>");
return sql.toString();
}

public static String getColumnEqualsHolder(EntityColumn column) {

return column.getColumn() + " = " + getColumnHolder(column);
}

public static String getColumnHolder(EntityColumn column) {

StringBuffer sb = new StringBuffer("#{");

sb.append("record.").append(column.getProperty());

if (column.getJdbcType() != null) {
sb.append(", jdbcType=");
sb.append(column.getJdbcType().toString());
}

if (column.getTypeHandler() != null) {
sb.append(", typeHandler=");
sb.append(column.getTypeHandler().getCanonicalName());
}

if (column.isUseJavaType() && !column.getJavaType().isArray()) {
sb.append(", javaType=");
sb.append(column.getJavaType().getCanonicalName());
}

sb.append("}");

return sb.toString();
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

whereAllIfColumns, getColumnEqualsHolder, and getColumnHolder duplicate existing core helpers (SqlHelper.getIfNotNull(entityName, ...) and EntityColumn.getColumnEqualsHolder(entityName)). Reusing the shared helpers will reduce maintenance risk and keep behavior consistent (e.g., version + logic-delete handling, JDBC/typeHandler formatting).

Suggested change
StringBuilder sql = new StringBuilder();
sql.append("<if test=\"");
sql.append("record.").append(column.getProperty()).append(" != null");
if (empty && column.getJavaType().equals(String.class)) {
sql.append(" and ").append(column.getProperty()).append(" != '' ");
}
sql.append("\">");
sql.append(contents);
sql.append("</if>");
return sql.toString();
}
public static String getColumnEqualsHolder(EntityColumn column) {
return column.getColumn() + " = " + getColumnHolder(column);
}
public static String getColumnHolder(EntityColumn column) {
StringBuffer sb = new StringBuffer("#{");
sb.append("record.").append(column.getProperty());
if (column.getJdbcType() != null) {
sb.append(", jdbcType=");
sb.append(column.getJdbcType().toString());
}
if (column.getTypeHandler() != null) {
sb.append(", typeHandler=");
sb.append(column.getTypeHandler().getCanonicalName());
}
if (column.isUseJavaType() && !column.getJavaType().isArray()) {
sb.append(", javaType=");
sb.append(column.getJavaType().getCanonicalName());
}
sb.append("}");
return sb.toString();
// Delegate to core helper to keep behavior (e.g., version and logic-delete handling) consistent
return SqlHelper.getIfNotNull("record", column, contents, empty);
}
public static String getColumnEqualsHolder(EntityColumn column) {
// Delegate to EntityColumn helper, using "record" as the entity alias
return column.getColumnEqualsHolder("record");
}
public static String getColumnHolder(EntityColumn column) {
// Delegate to EntityColumn helper, using "record" as the entity alias
return column.getColumnHolder("record");

Copilot uses AI. Check for mistakes.
type = SelectSpecifyColumnsProvider.class,
method = "dynamicSQL"
)
List<T> selectByPropertys(@Param("record") T record, @Param("fns") List<Fn<T, ?>> fns);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Public API method name selectByPropertys has a spelling error (“Propertys”). Since this is a new mapper method, consider renaming to selectByProperties (and the provider method accordingly) to avoid locking in a misspelled API.

Suggested change
List<T> selectByPropertys(@Param("record") T record, @Param("fns") List<Fn<T, ?>> fns);
List<T> selectByProperties(@Param("record") T record, @Param("fns") List<Fn<T, ?>> fns);

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +45
@SelectProvider(
type = SelectSpecifyColumnsProvider.class,
method = "dynamicSQL"
)
List<T> selectByColumns(@Param("record") T record, @Param("columns") List<String> columns);

/**
* 根据条件查询实体, 并指定属性
*
* @param record 查询实体条件
* @param fns 指定的返回实体属性
* @return
*/
@SelectProvider(
type = SelectSpecifyColumnsProvider.class,
method = "dynamicSQL"
)
List<T> selectByPropertys(@Param("record") T record, @Param("fns") List<Fn<T, ?>> fns);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

New mapper methods (selectByColumns / selectByPropertys) introduce new SQL-generation paths, but there are no corresponding tests under extra/src/test/java/tk/mybatis/mapper/additional/select (unlike SelectByPropertyMapperTest). Adding coverage that verifies selected columns, WHERE binding via record, and logic-delete behavior would help prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +34
StringBuilder sql = new StringBuilder();
sql.append("SELECT ");
sql.append("<foreach collection=\"columns\" item=\"item\" open=\"\" separator=\",\" close=\"\">");
sql.append("${item}");
sql.append("</foreach>");
sql.append(SqlHelper.fromTable(entityClass, this.tableName(entityClass)));
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

If columns is null or empty, the <foreach> renders nothing and produces invalid SQL (SELECT FROM ...). Add a guard (e.g., <choose>/<if>) to default to SqlHelper.selectAllColumns(entityClass) or throw a clear error when no columns are specified.

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +56
sql.append("SELECT ");
String entityClassName = entityClass.getName();
sql.append("<foreach collection=\"fns\" item=\"item\" open=\"\" separator=\",\" close=\"\">");
String ognl = new StringBuilder("${@")
.append(propertyHelper)
.append("@getColumnByProperty(@java.lang.Class@forName(\"")
.append(entityClassName)
.append("\"), @tk.mybatis.mapper.weekend.reflection.Reflections@fnToFieldName(item))}").toString();
sql.append(ognl);
sql.append("</foreach>");
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

If fns is null or empty, the <foreach> renders nothing and produces invalid SQL (SELECT FROM ...). Add a guard to default to all columns or fail fast with a helpful error when no properties are specified.

Copilot uses AI. Check for mistakes.

sql.append("record.").append(column.getProperty()).append(" != null");
if (empty && column.getJavaType().equals(String.class)) {
sql.append(" and ").append(column.getProperty()).append(" != '' ");
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

getIfNotNull builds the empty-string check as and <property> != '' but the preceding null-check uses record.<property>. This will cause OGNL evaluation errors (property not found) and the condition won’t work as intended. Prefix the empty-string check with record. as well (or delegate to SqlHelper.getIfNotNull("record", ...) to avoid drift).

Suggested change
sql.append(" and ").append(column.getProperty()).append(" != '' ");
sql.append(" and record.").append(column.getProperty()).append(" != '' ");

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants