Skip to content

Conversation

@stIncMale
Copy link
Member


public static final ObjectIdJdbcType INSTANCE = new ObjectIdJdbcType();
public static final MqlType MQL_TYPE = MqlType.OBJECT_ID;
public static final SQLType MQL_TYPE = MqlType.OBJECT_ID;
Copy link
Member Author

Choose a reason for hiding this comment

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

I made MqlType package-access, as it does not need to be public.

Copy link
Member Author

Choose a reason for hiding this comment

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

TODO @stIncMale Rename the field to SQL_TYPE.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 71c0d63.

typeContributions.contributeJavaType(ObjectIdJavaType.INSTANCE);
typeContributions.contributeJdbcType(ObjectIdJdbcType.INSTANCE);
var objectIdTypeCode = MqlType.OBJECT_ID.getVendorTypeNumber();
var objectIdTypeCode = ObjectIdJdbcType.MQL_TYPE.getVendorTypeNumber();
Copy link
Member Author

Choose a reason for hiding this comment

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

MqlType was made package-access. Furthermore, ObjectIdJdbcType.MQL_TYPE explicitly points to our implementation of the JdbcType for ObjectId, which improves readability.

throw exceptionDomainTypeUnsupportedOrMustBeExplicit(value, domainType);
}

public static @Nullable Object toDomainValue(BsonValue value) throws SQLFeatureNotSupportedException {
Copy link
Member Author

Choose a reason for hiding this comment

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

This PR only needed this new method. However, I also wanted to stop using Object.class to represent "unknown domain type", which caused the rest of the changes.

@Table(name = COLLECTION_NAME)
@SqlResultSetMapping(
name = ItemWithFlattenedValue.MAPPING_FOR_FLATTENED_VALUE,
columns = {
Copy link
Member Author

Choose a reason for hiding this comment

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

I tried also using SqlResultSetMapping.classes, but I don't think Hibernate ORM implements that one correctly: instead of trying to find the corresponding constructor, it uses the no-argument constructor and then tries to populate the object, searching for the field/property based on the ColumnResult.name, which represents the column name, and does not have to match the name of a field/property.

@stIncMale stIncMale force-pushed the HIBERNATE-60 branch 2 times, most recently from 02c39c7 to 51b953e Compare September 21, 2025 03:01
@stIncMale stIncMale marked this pull request as ready for review September 29, 2025 21:26
@stIncMale stIncMale requested a review from a team as a code owner September 29, 2025 21:26
@Table(name = COLLECTION_NAME)
static class ItemWithArrayAndCollectionValues {
@SqlResultSetMapping(
name = ItemWithArrayAndCollectionValues.MAPPING_FOR_ITEM,
Copy link
Member Author

Choose a reason for hiding this comment

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

TODO @stIncMale File a ticket about creating a static helper method project(ItemWithArrayAndCollectionValues.class, ItemWithArrayAndCollectionValues.MAPPING_FOR_ITEM) that constructs the $project stage.

Copy link
Member Author

Choose a reason for hiding this comment

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

* queries</a>, {@link QueryProducer#createNativeQuery(String, Class)}.
*/
@Test
void testScalar() {
Copy link
Member Author

Choose a reason for hiding this comment

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

TODO @stIncMale

Add

() -> {
    var mql = mql(COLLECTION_NAME, List.of(match(eq(itemWithNestedValue.id)), project(include("nested"))));
    assertEq(
            itemWithNestedValue.nested,
            session.createNativeQuery(mql, StructAggregateEmbeddableIntegrationTests.Plural.class).getSingleResult());
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in ac23fc3.

Comment on lines 622 to 624
if (fieldName.equals(ID_FIELD_NAME)) {
excludeId = true;
}
Copy link
Member

@vbabanin vbabanin Oct 16, 2025

Choose a reason for hiding this comment

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

[nit/optional]

Suggested change
if (fieldName.equals(ID_FIELD_NAME)) {
excludeId = true;
}
excludeId |= ID_FIELD_NAME.equals(fieldName);

Copy link
Member Author

Choose a reason for hiding this comment

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

Done in 942a177.

* Returning DTOs (Data Transfer Objects)</a>, {@link QueryProducer#createNativeQuery(String, Class)}.
*/
@Nested
class Dto {
Copy link
Member

@vbabanin vbabanin Oct 17, 2025

Choose a reason for hiding this comment

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

As I see, Hibernate supports DTO mapping both via Tuple and directly to an instance of DTO class with the help of @ConstructorResult. I suggest adding tests for latter approach as well to have wider use-case coverage.

To keep things simple, we could add @ConstructorResult to existing entities used in these tests (e.g., BasicCrudIntegrationTests.Item, etc.) rather than introducing new DTO-only classes (it works in both cases). Then we could extend the Dto nested test class with constructor-based variants (e.g., testBasicValues that uses constructor mapping):

() -> assertEq(
    item,
    session.createNativeQuery(mql, Item.CONSTRUCTOR_MAPPING_FOR_ITEM, Item.class)
           .getSingleResult());

Findings so far: constructor mapping works with entities that have only basic types, embeddables, or structs. It fails with Collection or subtypes - Hibernate ORM throws a NullPointerException because CollectionJavaType returns a null as recommended type. If array is used in @ColumnResult for a parameter that is Collection, the parametrized constructor is not invoked and Hibernate falls back to using the default constructor and field mapping.

@Override
	public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {
		// none
		return null;
	}

That looks like a Hibernate bug (regardless of whether collections are intended to be supported, given the non-descriptive error).

Given that, we can add/extend tests for:

ItemWithFlattenedValue
ItemWithNestedValue
ItemWithNestedValueHavingArraysAndCollections (collections are inside a struct, which our type handles)
BasicCrudIntegrationTests.Item

Partially implemented suggestion (excludes ItemWithNestedValueHavingArraysAndCollections): 4fc30d2

Copy link
Member Author

@stIncMale stIncMale Oct 22, 2025

Choose a reason for hiding this comment

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

Done in c78dcde. I based this commit on your commit (and there is credit for that), but I changed a fair bit.

Discussing it over Zoom may be faster.

stIncMale and others added 2 commits October 20, 2025 21:16
@stIncMale stIncMale requested a review from vbabanin October 22, 2025 04:15
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.

2 participants