hibernate/hibernate-orm · error · MappingException

Could not format discriminator value to SQL string

Error message

Could not format discriminator value to SQL string

What it means

DiscriminatorHelper.jdbcLiteral renders a discriminator value as a SQL literal for the active dialect by delegating to the discriminator type's JdbcLiteralFormatter; any exception from the formatter is wrapped in MappingException('Could not format discriminator value to SQL string'). The literal parsed fine but could not be emitted — typically a custom or unusual discriminator Java/JDBC type whose formatter rejects the value or lacks dialect support. Reached via getDiscriminatorSQLValue() during persister construction.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/persister/entity/DiscriminatorHelper.java:122

	}

	private static <T> String discriminatorSqlLiteral(
			BasicType<T> discriminatorType,
			PersistentClass persistentClass,
			Dialect dialect) {
		return jdbcLiteral(
				discriminatorType.getJavaTypeDescriptor().fromString( persistentClass.getDiscriminatorValue() ),
				discriminatorType.getJdbcLiteralFormatter(),
				dialect
		);
	}

	public static <T> String jdbcLiteral(T value, JdbcLiteralFormatter<T> formatter, Dialect dialect) {
		try {
			return formatter.toJdbcLiteral( value, dialect, null );
		}
		catch (Exception e) {
			throw new MappingException( "Could not format discriminator value to SQL string", e );
		}
	}

	/**
	 * Utility that computes the node type used in entity or embeddable type literals. Resolves to
	 * either the {@link org.hibernate.metamodel.mapping.DiscriminatorType}, for polymorphic
	 * domain types, or to {@link StandardBasicTypes#CLASS Class} for non-inherited ones.
	 */
	public static <T> SqmBindableType<? super T> getDiscriminatorType(
			SqmPathSource<T> domainType, NodeBuilder nodeBuilder) {
		final SqmPathSource<?> subPathSource = domainType.findSubPathSource( DISCRIMINATOR_ROLE_NAME );
		final SqmBindableType<?> type = subPathSource != null
				? subPathSource.getPathType()
				: nodeBuilder.getTypeConfiguration().getBasicTypeRegistry().resolve( StandardBasicTypes.CLASS );
		//noinspection unchecked
		return (SqmBindableType<? super T>) type;
	}
}

View on GitHub (pinned to fad1729dce)

Solutions

  1. Use a standard discriminator type (STRING/INTEGER/CHAR) via @DiscriminatorColumn
  2. Fix the custom type: implement/override JdbcLiteralFormatter so toJdbcLiteral() handles the discriminator value for every dialect you deploy on
  3. Add boot-time tests with each target dialect to catch formatter failures before deployment

Example fix

// before: custom type on the discriminator column lacking JdbcLiteralFormatter support
@DiscriminatorColumn(name = "kind", discriminatorType = STRING) // + XML applies custom type

// after: plain basic discriminator type with built-in formatter
@DiscriminatorColumn(name = "kind", discriminatorType = STRING)
Defensive patterns

Strategy: try-catch

Try / catch

try {
    SessionFactory sf = metadata.getSessionFactoryBuilder().build();
}
catch ( org.hibernate.MappingException e ) {
    // discriminator literal could not be rendered for the dialect
    throw new IllegalStateException("SessionFactory boot failed on dialect " + dialect + ": " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: A discriminator mapped with a custom BasicType/JavaType whose JdbcLiteralFormatter.toJdbcLiteral() throws for the mapped value; enum/char discriminators whose rendering path is unsupported on the target dialect; boot of the factory against a dialect the custom type never handled.

Common situations: Custom discriminator types introduced for legacy schemas; switching databases/dialects where literal rendering differs; values that parse via fromString() but cannot be rendered back.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/e8d3b24b6066176c. Report an issue: GitHub.