Skip to content

Commit 82aa14c

Browse files
committed
1 parent 6ceec9d commit 82aa14c

29 files changed

+3093
-215
lines changed

src/integrationTest/java/com/mongodb/hibernate/ArrayAndCollectionIntegrationTests.java

Lines changed: 700 additions & 0 deletions
Large diffs are not rendered by default.

src/integrationTest/java/com/mongodb/hibernate/BasicCrudIntegrationTests.java

Lines changed: 293 additions & 110 deletions
Large diffs are not rendered by default.

src/integrationTest/java/com/mongodb/hibernate/embeddable/EmbeddableIntegrationTests.java

Lines changed: 484 additions & 16 deletions
Large diffs are not rendered by default.

src/integrationTest/java/com/mongodb/hibernate/embeddable/StructAggregateEmbeddableIntegrationTests.java

Lines changed: 502 additions & 18 deletions
Large diffs are not rendered by default.

src/main/java/com/mongodb/hibernate/dialect/MongoAggregateSupport.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static java.lang.String.format;
2020

2121
import com.mongodb.hibernate.internal.FeatureNotSupportedException;
22+
import com.mongodb.hibernate.internal.type.MongoArrayJdbcType;
2223
import com.mongodb.hibernate.internal.type.MongoStructJdbcType;
2324
import org.hibernate.dialect.aggregate.AggregateSupportImpl;
2425
import org.hibernate.mapping.AggregateColumn;
@@ -38,10 +39,11 @@ public String aggregateComponentCustomReadExpression(
3839
AggregateColumn aggregateColumn,
3940
Column column) {
4041
var aggregateColumnType = aggregateColumn.getTypeCode();
41-
if (aggregateColumnType == MongoStructJdbcType.JDBC_TYPE.getVendorTypeNumber()) {
42+
if (aggregateColumnType == MongoStructJdbcType.JDBC_TYPE.getVendorTypeNumber()
43+
|| aggregateColumnType == MongoArrayJdbcType.HIBERNATE_SQL_TYPE) {
4244
return format(
43-
"unused from %s.aggregateComponentCustomReadExpression",
44-
MongoAggregateSupport.class.getSimpleName());
45+
"unused from %s.aggregateComponentCustomReadExpression for SQL type code [%d]",
46+
MongoAggregateSupport.class.getSimpleName(), aggregateColumnType);
4547
}
4648
throw new FeatureNotSupportedException(format("The SQL type code [%d] is not supported", aggregateColumnType));
4749
}
@@ -53,17 +55,19 @@ public String aggregateComponentAssignmentExpression(
5355
AggregateColumn aggregateColumn,
5456
Column column) {
5557
var aggregateColumnType = aggregateColumn.getTypeCode();
56-
if (aggregateColumnType == MongoStructJdbcType.JDBC_TYPE.getVendorTypeNumber()) {
58+
if (aggregateColumnType == MongoStructJdbcType.JDBC_TYPE.getVendorTypeNumber()
59+
|| aggregateColumnType == MongoArrayJdbcType.HIBERNATE_SQL_TYPE) {
5760
return format(
58-
"unused from %s.aggregateComponentAssignmentExpression",
59-
MongoAggregateSupport.class.getSimpleName());
61+
"unused from %s.aggregateComponentAssignmentExpression for SQL type code [%d]",
62+
MongoAggregateSupport.class.getSimpleName(), aggregateColumnType);
6063
}
6164
throw new FeatureNotSupportedException(format("The SQL type code [%d] is not supported", aggregateColumnType));
6265
}
6366

6467
@Override
6568
public boolean requiresAggregateCustomWriteExpressionRenderer(int aggregateSqlTypeCode) {
66-
if (aggregateSqlTypeCode == MongoStructJdbcType.JDBC_TYPE.getVendorTypeNumber()) {
69+
if (aggregateSqlTypeCode == MongoStructJdbcType.JDBC_TYPE.getVendorTypeNumber()
70+
|| aggregateSqlTypeCode == MongoArrayJdbcType.HIBERNATE_SQL_TYPE) {
6771
return false;
6872
}
6973
throw new FeatureNotSupportedException(format("The SQL type code [%d] is not supported", aggregateSqlTypeCode));

src/main/java/com/mongodb/hibernate/dialect/MongoDialect.java

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,20 @@
2020
import static java.lang.String.format;
2121

2222
import com.mongodb.hibernate.internal.translate.MongoTranslatorFactory;
23+
import com.mongodb.hibernate.internal.type.MongoArrayJdbcType;
24+
import com.mongodb.hibernate.internal.type.MongoBigDecimalJavaType;
25+
import com.mongodb.hibernate.internal.type.MongoBooleanJavaType;
26+
import com.mongodb.hibernate.internal.type.MongoBooleanPrimitiveArrayJavaType;
27+
import com.mongodb.hibernate.internal.type.MongoCharacterJavaType;
28+
import com.mongodb.hibernate.internal.type.MongoDoubleJavaType;
29+
import com.mongodb.hibernate.internal.type.MongoDoublePrimitiveArrayJavaType;
30+
import com.mongodb.hibernate.internal.type.MongoIntegerJavaType;
31+
import com.mongodb.hibernate.internal.type.MongoIntegerPrimitiveArrayJavaType;
32+
import com.mongodb.hibernate.internal.type.MongoLongJavaType;
33+
import com.mongodb.hibernate.internal.type.MongoLongPrimitiveArrayJavaType;
34+
import com.mongodb.hibernate.internal.type.MongoStringJavaType;
2335
import com.mongodb.hibernate.internal.type.MongoStructJdbcType;
36+
import com.mongodb.hibernate.internal.type.MqlType;
2437
import com.mongodb.hibernate.internal.type.ObjectIdJavaType;
2538
import com.mongodb.hibernate.internal.type.ObjectIdJdbcType;
2639
import com.mongodb.hibernate.jdbc.MongoConnectionProvider;
@@ -31,6 +44,7 @@
3144
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
3245
import org.hibernate.service.ServiceRegistry;
3346
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
47+
import org.hibernate.type.descriptor.sql.internal.DdlTypeImpl;
3448
import org.jspecify.annotations.Nullable;
3549

3650
/**
@@ -91,9 +105,37 @@ public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
91105
@Override
92106
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
93107
super.contribute(typeContributions, serviceRegistry);
108+
typeContributions.contributeJavaType(MongoCharacterJavaType.INSTANCE);
109+
typeContributions.contributeJavaType(MongoIntegerJavaType.INSTANCE);
110+
typeContributions.contributeJavaType(MongoIntegerPrimitiveArrayJavaType.INSTANCE);
111+
typeContributions.contributeJavaType(MongoLongJavaType.INSTANCE);
112+
typeContributions.contributeJavaType(MongoLongPrimitiveArrayJavaType.INSTANCE);
113+
typeContributions.contributeJavaType(MongoDoubleJavaType.INSTANCE);
114+
typeContributions.contributeJavaType(MongoDoublePrimitiveArrayJavaType.INSTANCE);
115+
typeContributions.contributeJavaType(MongoBooleanJavaType.INSTANCE);
116+
typeContributions.contributeJavaType(MongoBooleanPrimitiveArrayJavaType.INSTANCE);
117+
typeContributions.contributeJavaType(MongoStringJavaType.INSTANCE);
118+
typeContributions.contributeJavaType(MongoBigDecimalJavaType.INSTANCE);
119+
contributeObjectIdType(typeContributions);
120+
typeContributions.contributeJdbcTypeConstructor(MongoArrayJdbcType.Constructor.INSTANCE);
121+
typeContributions.contributeJdbcType(MongoStructJdbcType.INSTANCE);
122+
}
123+
124+
private void contributeObjectIdType(TypeContributions typeContributions) {
94125
typeContributions.contributeJavaType(ObjectIdJavaType.INSTANCE);
95126
typeContributions.contributeJdbcType(ObjectIdJdbcType.INSTANCE);
96-
typeContributions.contributeJdbcType(MongoStructJdbcType.INSTANCE);
127+
var objectIdTypeCode = MqlType.OBJECT_ID.getVendorTypeNumber();
128+
typeContributions
129+
.getTypeConfiguration()
130+
.getDdlTypeRegistry()
131+
.addDescriptorIfAbsent(
132+
objectIdTypeCode,
133+
new DdlTypeImpl(
134+
objectIdTypeCode,
135+
format(
136+
"unused from %s.contributeObjectIdType for SQL type code [%d]",
137+
MongoDialect.class.getSimpleName(), objectIdTypeCode),
138+
this));
97139
}
98140

99141
@Override
@@ -105,4 +147,9 @@ public void contribute(TypeContributions typeContributions, ServiceRegistry serv
105147
public AggregateSupport getAggregateSupport() {
106148
return MongoAggregateSupport.INSTANCE;
107149
}
150+
151+
@Override
152+
public boolean supportsStandardArrays() {
153+
return true;
154+
}
108155
}

src/main/java/com/mongodb/hibernate/internal/translate/AbstractMqlTranslator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,9 @@ private static boolean isComparingFieldWithValue(ComparisonPredicate comparisonP
950950
}
951951

952952
private static BsonValue toBsonValue(Object value) {
953+
// TODO-HIBERNATE-74 decide if `value` is nullable and the method may return `null`
953954
try {
954-
return ValueConversions.toBsonValue(value);
955+
return assertNotNull(ValueConversions.toBsonValue(value));
955956
} catch (SQLFeatureNotSupportedException e) {
956957
throw new FeatureNotSupportedException(e);
957958
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2025-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.hibernate.internal.type;
18+
19+
import static com.mongodb.hibernate.internal.MongoAssertions.assertTrue;
20+
21+
import java.io.Serial;
22+
import java.sql.JDBCType;
23+
import java.sql.SQLException;
24+
import org.hibernate.dialect.Dialect;
25+
import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
26+
import org.hibernate.type.SqlTypes;
27+
import org.hibernate.type.descriptor.WrapperOptions;
28+
import org.hibernate.type.descriptor.jdbc.ArrayJdbcType;
29+
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
30+
import org.hibernate.type.descriptor.jdbc.JdbcType;
31+
import org.hibernate.type.descriptor.jdbc.JdbcTypeConstructor;
32+
import org.hibernate.type.spi.TypeConfiguration;
33+
import org.jspecify.annotations.Nullable;
34+
35+
/** Thread-safe. */
36+
public final class MongoArrayJdbcType extends ArrayJdbcType {
37+
@Serial
38+
private static final long serialVersionUID = 1L;
39+
40+
public static final JDBCType JDBC_TYPE = JDBCType.ARRAY;
41+
public static final int HIBERNATE_SQL_TYPE = SqlTypes.STRUCT_ARRAY;
42+
43+
private MongoArrayJdbcType(JdbcType elementJdbcType) {
44+
super(elementJdbcType);
45+
}
46+
47+
@Override
48+
public int getJdbcTypeCode() {
49+
var result = super.getJdbcTypeCode();
50+
assertTrue(result == JDBC_TYPE.getVendorTypeNumber());
51+
return result;
52+
}
53+
54+
@Override
55+
protected <X> @Nullable X getArray(
56+
BasicExtractor<X> extractor, java.sql.@Nullable Array array, WrapperOptions options) throws SQLException {
57+
return super.getArray(extractor, array, options);
58+
}
59+
60+
public static final class Constructor implements JdbcTypeConstructor {
61+
public static final Constructor INSTANCE = new Constructor();
62+
63+
private Constructor() {}
64+
65+
@Override
66+
public JdbcType resolveType(
67+
TypeConfiguration typeConfiguration,
68+
Dialect dialect,
69+
JdbcType elementType,
70+
ColumnTypeInformation columnTypeInformation) {
71+
return new MongoArrayJdbcType(elementType);
72+
}
73+
74+
@Override
75+
public int getDefaultSqlTypeCode() {
76+
return JDBC_TYPE.getVendorTypeNumber();
77+
}
78+
}
79+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2025-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.hibernate.internal.type;
18+
19+
import static com.mongodb.hibernate.internal.type.ValueConversions.toBigDecimalDomainValue;
20+
21+
import java.io.Serial;
22+
import java.math.BigDecimal;
23+
import org.bson.BsonValue;
24+
import org.hibernate.type.descriptor.WrapperOptions;
25+
import org.hibernate.type.descriptor.java.BigDecimalJavaType;
26+
import org.jspecify.annotations.Nullable;
27+
28+
/** Thread-safe. */
29+
public final class MongoBigDecimalJavaType extends BigDecimalJavaType {
30+
@Serial
31+
private static final long serialVersionUID = 1L;
32+
33+
public static final MongoBigDecimalJavaType INSTANCE = new MongoBigDecimalJavaType();
34+
35+
private MongoBigDecimalJavaType() {}
36+
37+
@Override
38+
public <X> @Nullable BigDecimal wrap(@Nullable X value, WrapperOptions options) {
39+
if (value instanceof BsonValue v) {
40+
return toBigDecimalDomainValue(v);
41+
}
42+
return super.wrap(value, options);
43+
}
44+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2025-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.hibernate.internal.type;
18+
19+
import static com.mongodb.hibernate.internal.type.ValueConversions.toBooleanDomainValue;
20+
21+
import java.io.Serial;
22+
import org.bson.BsonValue;
23+
import org.hibernate.type.descriptor.WrapperOptions;
24+
import org.hibernate.type.descriptor.java.BooleanJavaType;
25+
import org.jspecify.annotations.Nullable;
26+
27+
/** Thread-safe. */
28+
public final class MongoBooleanJavaType extends BooleanJavaType {
29+
@Serial
30+
private static final long serialVersionUID = 1L;
31+
32+
public static final MongoBooleanJavaType INSTANCE = new MongoBooleanJavaType();
33+
34+
private MongoBooleanJavaType() {}
35+
36+
@Override
37+
public <X> @Nullable Boolean wrap(@Nullable X value, WrapperOptions options) {
38+
if (value instanceof BsonValue v) {
39+
return toBooleanDomainValue(v);
40+
}
41+
return super.wrap(value, options);
42+
}
43+
}

0 commit comments

Comments
 (0)