You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从EclipseLink的ClassDescriptor中获取待删除记录的ID值?

软删除定制器添加删除者信息的实现方案

现有运行的软删除定制器代码

public class SoftDeleteCustomizer implements DescriptorCustomizer {

  @Override
  public void customize(ClassDescriptor descriptor) {
    descriptor.getQueryManager().setDeleteSQLString(
        String.format("UPDATE %s SET record_status = 'D', record_status_time = CURRENT_TIMESTAMP WHERE id = #ID",
                      descriptor.getTableName()
        )
    );
  }

}

需求与问题

需要在软删除操作中添加记录删除者的信息,倾向于用参数方式传递,但使用DeleteObjectQuery时,不知道如何获取待删除记录的ID/主键值来设置参数。当前尝试的代码如下:

@Override
public void customize(final ClassDescriptor descriptor) {
  final DeleteObjectQuery query = new DeleteObjectQuery();
  query.addArgument("DELETED_BY", String.class);
  query.addArgument("ID", Long.class);
  query.addArgumentValue(SecurityUtils.getUsername());
  query.addArgumentValue(...); // 不知道如何获取待删除记录的ID
  query.setSQLString(String.format(DELETE_SQL, descriptor.getTableName()));
  descriptor.getQueryManager().setDeleteQuery(query);
}

解决方案

不需要手动添加ID参数并赋值,EclipseLink的DeleteObjectQuery会自动处理主键参数绑定。可以通过查询事件动态注入删除者信息,同时利用框架特性自动绑定主键值,具体实现如下:

方式一:适配任意主键(单/复合主键)

public class SoftDeleteCustomizer implements DescriptorCustomizer {
    private static final String DELETE_SQL_TEMPLATE = "UPDATE %s SET record_status = 'D', record_status_time = CURRENT_TIMESTAMP, deleted_by = ? WHERE %s";

    @Override
    public void customize(final ClassDescriptor descriptor) {
        // 动态构建主键WHERE子句,适配单/复合主键
        List<DatabaseField> primaryKeyFields = descriptor.getPrimaryKeyFields();
        StringBuilder whereClause = new StringBuilder();
        for (int i = 0; i < primaryKeyFields.size(); i++) {
            DatabaseField field = primaryKeyFields.get(i);
            if (i > 0) {
                whereClause.append(" AND ");
            }
            whereClause.append(field.getName()).append(" = #").append(field.getName());
        }

        // 构建完整软删除SQL
        String deleteSql = String.format(DELETE_SQL_TEMPLATE, descriptor.getTableName(), whereClause.toString());

        // 配置DeleteObjectQuery
        DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
        deleteQuery.setSQLString(deleteSql);

        // 添加查询监听器,在执行前注入删除者信息
        deleteQuery.addQueryListener(new QueryAdapter() {
            @Override
            public void prepareQuery(DatabaseQuery query, Record record, Session session) {
                DatabaseCall call = query.getDatabaseCall();
                // 注入当前登录用户名到参数中
                call.addArgumentValue(SecurityUtils.getUsername());
            }
        });

        descriptor.getQueryManager().setDeleteQuery(deleteQuery);
    }
}

方式二:已知主键字段名(简化版)

如果确定实体主键字段名为id,可以直接写死占位符,代码更简洁:

public class SoftDeleteCustomizer implements DescriptorCustomizer {
    private static final String DELETE_SQL_TEMPLATE = "UPDATE %s SET record_status = 'D', record_status_time = CURRENT_TIMESTAMP, deleted_by = ? WHERE id = #id";

    @Override
    public void customize(final ClassDescriptor descriptor) {
        String deleteSql = String.format(DELETE_SQL_TEMPLATE, descriptor.getTableName());

        DeleteObjectQuery deleteQuery = new DeleteObjectQuery();
        deleteQuery.setSQLString(deleteSql);

        deleteQuery.addQueryListener(new QueryAdapter() {
            @Override
            public void prepareQuery(DatabaseQuery query, Record record, Session session) {
                DatabaseCall call = query.getDatabaseCall();
                call.addArgumentValue(SecurityUtils.getUsername());
            }
        });

        descriptor.getQueryManager().setDeleteQuery(deleteQuery);
    }
}

关键说明

  • #字段名是EclipseLink的参数占位符,框架会自动从待删除实体中对应字段取值并绑定,无需手动设置ID参数。
  • 使用QueryListener的prepareQuery方法注入删除者信息,该方法在查询执行前触发,能获取到当前上下文的用户名,避免在定制器初始化时无法获取动态数据的问题。

内容的提问来源于stack exchange,提问作者Jasper de Vries

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:45:45