elunez/eladmin · warning · EntityExistException

${className} with ${column.columnName} {} existed

Error message

${className} with ${column.columnName} {} existed

What it means

Not a runtime throw but a FreeMarker template line in the code generator (ServiceImpl.ftl): for every column flagged UNIQUE in the inspected table, the generated service's create() calls `repository.findBy<Column>(...) != null` and throws EntityExistException("${className} with ${column.columnName} {} existed", value). At generation time the placeholders ${className}/${column.columnName} are filled; at runtime of the GENERATED code this fires when inserting a row whose unique column value already exists.

Source

Thrown at eladmin-generator/src/main/resources/template/admin/ServiceImpl.ftl:103

        ValidationUtil.isNull(${changeClassName}.get${pkCapitalColName}(),"${className}","${pkChangeColName}",${pkChangeColName});
        return ${changeClassName}Mapper.toDto(${changeClassName});
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(${className} resources) {
<#if !auto && pkColumnType = 'Long'>
        Snowflake snowflake = IdUtil.createSnowflake(1, 1);
        resources.set${pkCapitalColName}(snowflake.nextId()); 
</#if>
<#if !auto && pkColumnType = 'String'>
        resources.set${pkCapitalColName}(IdUtil.simpleUUID()); 
</#if>
<#if columns??>
    <#list columns as column>
    <#if column.columnKey = 'UNI'>
        if(${changeClassName}Repository.findBy${column.capitalColumnName}(resources.get${column.capitalColumnName}()) != null){
            throw new EntityExistException(${className}.class,"${column.columnName}",resources.get${column.capitalColumnName}());
        }
    </#if>
    </#list>
</#if>
        ${changeClassName}Repository.save(resources);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(${className} resources) {
        ${className} ${changeClassName} = ${changeClassName}Repository.findById(resources.get${pkCapitalColName}()).orElseGet(${className}::new);
        ValidationUtil.isNull( ${changeClassName}.get${pkCapitalColName}(),"${className}","id",resources.get${pkCapitalColName}());
<#if columns??>
    <#list columns as column>
        <#if column.columnKey = 'UNI'>
        <#if column_index = 1>
        ${className} ${changeClassName}1 = null;
        </#if>

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Submit a value not yet present for the unique column (check via the generated list/query endpoint first).
  2. If duplicates keep occurring from double clicks, debounce/disable the submit button until the response.
  3. For concurrent creates, rely on/also handle the DB unique constraint (catch DataIntegrityViolationException) since the findBy-then-save check is not atomic.
  4. Adjust the .ftl template to generate an upsert or a friendlier message if you control the generator templates.
  5. Regenerate the module after changing the table's unique keys so the guards match reality.

Example fix

// before (generated code pattern)
if(userRepository.findByUsername(resources.getUsername()) != null){
    throw new EntityExistException(User.class, "username", resources.getUsername());
}
userRepository.save(resources);

// after: also handle the race via the DB constraint
try {
    userRepository.save(resources);
} catch (DataIntegrityViolationException e) {
    throw new EntityExistException(User.class, "username", resources.getUsername());
}
Defensive patterns

Strategy: validation

Validate before calling

// pre-check uniqueness through the generated query API
boolean taken = client.getByUsername(dto.getUsername()) != null;
if (taken) { toast('用户名已存在'); return; }

Try / catch

try { create(dto); } catch (EntityExistException e) { // e.getMessage() contains "with username ... existed": show duplicate-field error on that input } catch (DataIntegrityViolationException e) { // race lost to the DB constraint: same user-facing message }

Prevention

When it happens

Trigger: Generating a module from a table with one or more UNIQUE-key columns, then calling the generated POST create endpoint with a value for that column that is already stored — e.g. creating a user with an existing username, a dict with an existing name.

Common situations: Duplicate submissions in the generated admin UI; import scripts colliding with existing rows; race conditions where two concurrent creates pass the findBy check and the DB unique constraint then throws a DataIntegrityViolationException instead; tables whose unique index is composite (this template only guards single-column UNI).

Related errors


AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14). Data as JSON: /api/errors/445e9c367f3b9fc7. Report an issue: GitHub.