Skip to content

Conversation

@RealTake
Copy link

@RealTake RealTake commented Nov 24, 2025

Add @CollectionTableOverride annotation for embeddable collections

This change was introduced to address a limitation in Hibernate where
entities cannot override the @CollectionTable(name = ...) defined inside an embeddable class.
When multiple entities share the same embeddable, it becomes impossible to customize the collection table name per entity, causing conflicts in DDL generation or preventing reuse of embeddable components.

To fix this, a new annotation (@CollectionTableOverride) was implemented, allowing entities to override the collection table name for collections declared inside embeddable classes.

  • Add CollectionTableOverride and CollectionTableOverrides annotations
  • Support overriding collection table name for collections within embeddable classes
  • Implement field-level annotation lookup in CollectionBinder
  • Improve path matching logic using BinderHelper.getRelativePath()
  • Enable DDL generation and query generation with overridden table names

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license
and can be relicensed under the terms of the LGPL v2.1 license in the future at the maintainers' discretion.
For more information on licensing, please check here.


https://hibernate.atlassian.net/browse/HHH-19952

@hibernate-github-bot
Copy link

hibernate-github-bot bot commented Nov 24, 2025

Thanks for your pull request!

This pull request appears to follow the contribution rules.

› This message was automatically generated.

@RealTake RealTake changed the title Add @CollectionTableOverride to override collection table names… Add @CollectionTableOverride annotation for embeddable collections Nov 24, 2025
Copy link
Member

@gavinking gavinking left a comment

Choose a reason for hiding this comment

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

Two requests:

  1. we should allow the user to specify a whole CollectionTable nested annotation, and
  2. the code formatting should be adjusted to follow the Hibernate conventions (spaces around parenthesized expressions).


// Get the ClassDetails from the models context
final var modelsContext = buildingContext.getBootstrapContext().getModelsContext();
final ClassDetails entityClassDetails = modelsContext.getClassDetailsRegistry()
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
final ClassDetails entityClassDetails = modelsContext.getClassDetailsRegistry()
final var entityClassDetails = modelsContext.getClassDetailsRegistry()

/**
* The name of the collection table to use instead of the default.
*/
String table();
Copy link
Member

Choose a reason for hiding this comment

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

I believe we should make this jakarta.persistence.CollectionTable table() instead of just a string table name.

This is analogous to how AttributeOverride has Column column().

}
}
if (entityField == null) {
for (MemberDetails member : entityClassDetails.getMethods()) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
for (MemberDetails member : entityClassDetails.getMethods()) {
for ( var member : entityClassDetails.getMethods() ) {

MemberDetails entityField = null;
try {
// Try to get the property from the entity class
for (MemberDetails member : entityClassDetails.getFields()) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
for (MemberDetails member : entityClassDetails.getFields()) {
for ( var member : entityClassDetails.getFields() ) {

private String name;

@Embedded
@CollectionTableOverride(name = "phones", table = "person_phones")
Copy link
Member

Choose a reason for hiding this comment

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

Did you try @AssociationOverride(name = "phones", joinTable = @JoinTable(name = "person_phones"))? It seems to me that the annotation would already serve the purpose for overriding the table name as well as join columns. I'd also say that using the existing annotation would be preferable to creating new ones.

Copy link
Member

@gavinking gavinking Nov 24, 2025

Choose a reason for hiding this comment

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

Rrrrrmrmmrrmmmm .... maybe.

Not sure I agree here, @beikov. It's pretty clear that in JPA @AssociationOverride is intended for overriding a @JoinTable, not for overriding a @CollectionTable.

Now, what's the difference between a @JoinTable and a @CollectionTable? Not a whole lot I suppose, and so yes, perhaps we could abuse the @AssociationOverride annotation for this, but it would be an abuse.

Perhaps this is something that should be addressed at the spec level with a new @ElementCollectionOverride annotation. Dunno.

Copy link
Member

@beikov beikov Nov 24, 2025

Choose a reason for hiding this comment

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

Well actually, I just found this section of the spec:

To override the default properties of the column used for a basic type, the Column annotation is used on the collection-valued attribute in addition to the ElementCollection annotation. The value of the table element of the Column annotation defaults to the name of the collection table.

To override these defaults for an embeddable class, the AttributeOverride and/or AttributeOverrides annotations must be used in addition to the ElementCollection annotation. The value of the table element of the Column annotation used in the AttributeOverride annotation defaults to the name of the collection table. If the embeddable class contains references to other entities, the default values for the columns corresponding to those references may be overridden by means of the AssociationOverride and/or AssociationOverrides annotations.

So I guess by overriding every column with @AttributeOverride and specifying a table it would be overridden?

Copy link
Member

Choose a reason for hiding this comment

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

But then there is also this section:

A collection table is created for the mapping of an element collection. See Section 11.1.8 for the rules that apply to the generation of collection tables. The Column, AttributeOverride, and AssociationOverride annotations may be used to override CollectionTable mappings, as described in Section 11.1.9, Section 11.1.4, and Section 11.1.2 respectively.

Copy link
Member

Choose a reason for hiding this comment

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

Pfffffffffff shit I have little idea what that means.

But I don't think it means what you're suggestion. I think it's much more likely talking about the case where you have the embeddable as the element of the collection.

final String fieldName;
if (fullPath.contains(".")) {
fieldName = fullPath.substring(0, fullPath.indexOf('.'));
} else {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
} else {
}
else {

String overrideName,
PropertyHolder propertyHolder,
MemberDetails property,
PropertyData inferredData) {

Check notice

Code scanning / CodeQL

Useless parameter

The parameter 'inferredData' is never used.
Replace table name string with nested @CollectionTable annotation
to allow full collection table configuration override, including
schema, catalog, joinColumns, indexes, and other attributes.
@RealTake RealTake requested a review from gavinking November 24, 2025 10:45
@RealTake RealTake force-pushed the main branch 2 times, most recently from 29cfa63 to 43ced16 Compare November 24, 2025 12:37
@RealTake
Copy link
Author

@gavinking

I’ve applied your requests.

Two requests:

  1. we should allow the user to specify a whole CollectionTable nested annotation, and
  2. the code formatting should be adjusted to follow the Hibernate conventions (spaces around parenthesized expressions).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants