Skip to content

Commit 182d8fc

Browse files
implement loading by primary key
1 parent 499e600 commit 182d8fc

25 files changed

+621
-55
lines changed

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

+21
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,27 @@ void testDynamicUpdate() {
198198
}
199199
}
200200

201+
@Nested
202+
class LoadByIdTests {
203+
204+
@Test
205+
void testLoad() {
206+
var book = new Book();
207+
book.id = 1;
208+
book.title = "In Search of Lost Time";
209+
book.publishYear = 1913;
210+
211+
sessionFactoryScope.inTransaction(session -> session.persist(book));
212+
213+
var loadedBook = sessionFactoryScope.fromTransaction(session -> {
214+
var loaded = new Book();
215+
session.load(loaded, 1);
216+
return loaded;
217+
});
218+
assertThat(loadedBook).usingRecursiveComparison().isEqualTo(book);
219+
}
220+
}
221+
201222
private static void assertCollectionContainsExactly(BsonDocument expectedDoc) {
202223
assertThat(mongoCollection.find()).containsExactly(expectedDoc);
203224
}

src/integrationTest/resources/logback-test.xml

+2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
<logger name="org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator" level="debug" additivity="true"/>
1111
<logger name="org.hibernate.SQL" level="debug" additivity="true"/>
1212
<logger name="org.hibernate.orm.jdbc.bind" level="trace" additivity="true"/>
13+
<logger name="org.hibernate.orm.jdbc.extract" level="trace" additivity="true"/>
1314
<logger name="org.hibernate.persister.entity" level="debug" additivity="true"/>
15+
<logger name="org.hibernate.orm.sql.ast.tree" level="debug" additivity="true"/>
1416
<logger name="org.mongodb.driver" level="warn" additivity="true"/>
1517
<logger name="com.mongodb.hibernate" level="debug" additivity="true"/>
1618
<root level="info">

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

+111-39
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,18 @@
1919
import static com.mongodb.hibernate.internal.MongoAssertions.assertNotNull;
2020
import static com.mongodb.hibernate.internal.MongoAssertions.assertTrue;
2121
import static com.mongodb.hibernate.internal.MongoConstants.ID_FIELD_NAME;
22+
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.COLLECTION_AGGREGATE;
2223
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.COLLECTION_MUTATION;
24+
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.COLLECTION_NAME;
25+
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.FIELD_NAME;
2326
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.FIELD_VALUE;
27+
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.FILTER;
28+
import static com.mongodb.hibernate.internal.translate.AstVisitorValueDescriptor.PROJECT_STAGE_SPECIFICATIONS;
29+
import static com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.stage.AstProjectStageSpecification.include;
2430
import static com.mongodb.hibernate.internal.translate.mongoast.filter.AstComparisonFilterOperator.EQ;
2531
import static java.lang.String.format;
32+
import static org.hibernate.query.sqm.ComparisonOperator.EQUAL;
33+
import static org.hibernate.sql.ast.SqlTreePrinter.logSqlAst;
2634

2735
import com.mongodb.hibernate.internal.FeatureNotSupportedException;
2836
import com.mongodb.hibernate.internal.extension.service.StandardServiceRegistryScopedState;
@@ -31,23 +39,33 @@
3139
import com.mongodb.hibernate.internal.translate.mongoast.AstFieldUpdate;
3240
import com.mongodb.hibernate.internal.translate.mongoast.AstNode;
3341
import com.mongodb.hibernate.internal.translate.mongoast.AstParameterMarker;
42+
import com.mongodb.hibernate.internal.translate.mongoast.command.AstAggregateCommand;
43+
import com.mongodb.hibernate.internal.translate.mongoast.command.AstCommand;
3444
import com.mongodb.hibernate.internal.translate.mongoast.command.AstDeleteCommand;
3545
import com.mongodb.hibernate.internal.translate.mongoast.command.AstInsertCommand;
3646
import com.mongodb.hibernate.internal.translate.mongoast.command.AstUpdateCommand;
47+
import com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.AstPipeline;
48+
import com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.AstStage;
49+
import com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.stage.AstMatchStage;
50+
import com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.stage.AstProjectStage;
51+
import com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.stage.AstProjectStageSpecification;
3752
import com.mongodb.hibernate.internal.translate.mongoast.filter.AstComparisonFilterOperation;
3853
import com.mongodb.hibernate.internal.translate.mongoast.filter.AstFieldOperationFilter;
3954
import com.mongodb.hibernate.internal.translate.mongoast.filter.AstFilter;
4055
import com.mongodb.hibernate.internal.translate.mongoast.filter.AstFilterFieldPath;
56+
import com.mongodb.hibernate.internal.translate.mongoast.filter.AstMatchesEverythingFilter;
4157
import java.io.IOException;
4258
import java.io.StringWriter;
4359
import java.util.ArrayList;
60+
import java.util.HashSet;
4461
import java.util.List;
4562
import java.util.Set;
4663
import org.bson.json.JsonMode;
4764
import org.bson.json.JsonWriter;
4865
import org.bson.json.JsonWriterSettings;
4966
import org.hibernate.engine.spi.SessionFactoryImplementor;
5067
import org.hibernate.internal.util.collections.Stack;
68+
import org.hibernate.persister.entity.EntityPersister;
5169
import org.hibernate.persister.internal.SqlFragmentPredicate;
5270
import org.hibernate.query.sqm.tree.expression.Conversion;
5371
import org.hibernate.sql.ast.Clause;
@@ -92,6 +110,7 @@
92110
import org.hibernate.sql.ast.tree.from.FunctionTableReference;
93111
import org.hibernate.sql.ast.tree.from.NamedTableReference;
94112
import org.hibernate.sql.ast.tree.from.QueryPartTableReference;
113+
import org.hibernate.sql.ast.tree.from.StandardTableGroup;
95114
import org.hibernate.sql.ast.tree.from.TableGroup;
96115
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
97116
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
@@ -143,6 +162,8 @@ abstract class AbstractMqlTranslator<T extends JdbcOperation> implements SqlAstT
143162

144163
private final List<JdbcParameterBinder> parameterBinders = new ArrayList<>();
145164

165+
private final Set<String> affectedTableNames = new HashSet<>();
166+
146167
AbstractMqlTranslator(SessionFactoryImplementor sessionFactory) {
147168
this.sessionFactory = sessionFactory;
148169
assertNotNull(sessionFactory
@@ -178,7 +199,7 @@ public Stack<Clause> getCurrentClauseStack() {
178199

179200
@Override
180201
public Set<String> getAffectedTableNames() {
181-
throw new FeatureNotSupportedException("TODO-HIBERNATE-22 https://jira.mongodb.org/browse/HIBERNATE-22");
202+
return affectedTableNames;
182203
}
183204

184205
List<JdbcParameterBinder> getParameterBinders() {
@@ -197,12 +218,12 @@ static String renderMongoAstNode(AstNode rootAstNode) {
197218
}
198219

199220
@SuppressWarnings("overloads")
200-
<R extends AstNode> R acceptAndYield(Statement statement, AstVisitorValueDescriptor<R> resultDescriptor) {
221+
<R extends AstCommand> R acceptAndYield(Statement statement, AstVisitorValueDescriptor<R> resultDescriptor) {
201222
return astVisitorValueHolder.execute(resultDescriptor, () -> statement.accept(this));
202223
}
203224

204225
@SuppressWarnings("overloads")
205-
<R extends AstNode> R acceptAndYield(SqlAstNode node, AstVisitorValueDescriptor<R> resultDescriptor) {
226+
<R> R acceptAndYield(SqlAstNode node, AstVisitorValueDescriptor<R> resultDescriptor) {
206227
return astVisitorValueHolder.execute(resultDescriptor, () -> node.accept(this));
207228
}
208229

@@ -214,20 +235,18 @@ public void visitStandardTableInsert(TableInsertStandard tableInsert) {
214235
if (tableInsert.getNumberOfReturningColumns() > 0) {
215236
throw new FeatureNotSupportedException();
216237
}
217-
var tableName = tableInsert.getTableName();
218238
var astElements = new ArrayList<AstElement>(tableInsert.getNumberOfValueBindings());
219239
for (var columnValueBinding : tableInsert.getValueBindings()) {
220240
var columnExpression = columnValueBinding.getColumnReference().getColumnExpression();
221241

222242
var valueExpression = columnValueBinding.getValueExpression();
223-
if (valueExpression == null) {
224-
throw new FeatureNotSupportedException();
225-
}
226243
var astValue = acceptAndYield(valueExpression, FIELD_VALUE);
227244

228245
astElements.add(new AstElement(columnExpression, astValue));
229246
}
230-
astVisitorValueHolder.yield(COLLECTION_MUTATION, new AstInsertCommand(tableName, new AstDocument(astElements)));
247+
astVisitorValueHolder.yield(
248+
COLLECTION_MUTATION,
249+
new AstInsertCommand(tableInsert.getMutatingTable().getTableName(), new AstDocument(astElements)));
231250
}
232251

233252
@Override
@@ -300,8 +319,91 @@ public void visitParameter(JdbcParameter jdbcParameter) {
300319
}
301320

302321
@Override
322+
@SuppressWarnings("OperatorPrecedence")
303323
public void visitSelectStatement(SelectStatement selectStatement) {
304-
throw new FeatureNotSupportedException("TODO-HIBERNATE-22 https://jira.mongodb.org/browse/HIBERNATE-22");
324+
logSqlAst(selectStatement);
325+
if (!selectStatement.getQueryPart().isRoot()) {
326+
throw new FeatureNotSupportedException("Subquery not supported");
327+
}
328+
if (selectStatement.getCteStatements() != null
329+
&& !selectStatement.getCteStatements().isEmpty()
330+
|| selectStatement.getCteObjects() != null
331+
&& !selectStatement.getCteObjects().isEmpty()) {
332+
throw new FeatureNotSupportedException("CTE feature not supported");
333+
}
334+
selectStatement.getQueryPart().accept(this);
335+
}
336+
337+
@Override
338+
public void visitQuerySpec(QuerySpec querySpec) {
339+
var collection = acceptAndYield(assertNotNull(querySpec.getFromClause()), COLLECTION_NAME);
340+
341+
var whereClauseRestrictions = querySpec.getWhereClauseRestrictions();
342+
var filter = whereClauseRestrictions == null || whereClauseRestrictions.isEmpty()
343+
? AstMatchesEverythingFilter.INSTANCE
344+
: acceptAndYield(whereClauseRestrictions, FILTER);
345+
346+
var projectStageSpecifications = acceptAndYield(querySpec.getSelectClause(), PROJECT_STAGE_SPECIFICATIONS);
347+
348+
var stages = List.<AstStage>of(new AstMatchStage(filter), new AstProjectStage(projectStageSpecifications));
349+
astVisitorValueHolder.yield(COLLECTION_AGGREGATE, new AstAggregateCommand(collection, new AstPipeline(stages)));
350+
}
351+
352+
@Override
353+
public void visitFromClause(FromClause fromClause) {
354+
if (fromClause.getRoots().size() == 1
355+
&& fromClause.getRoots().get(0) instanceof StandardTableGroup standardTableGroup
356+
&& standardTableGroup.getModelPart() instanceof EntityPersister entityPersister
357+
&& entityPersister.getQuerySpaces().length == 1) {
358+
affectedTableNames.add(((String[]) entityPersister.getQuerySpaces())[0]);
359+
standardTableGroup.getPrimaryTableReference().accept(this);
360+
}
361+
throw new FeatureNotSupportedException();
362+
}
363+
364+
@Override
365+
public void visitNamedTableReference(NamedTableReference namedTableReference) {
366+
astVisitorValueHolder.yield(COLLECTION_NAME, namedTableReference.getTableExpression());
367+
}
368+
369+
@Override
370+
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
371+
var fieldName = acceptAndYield(comparisonPredicate.getLeftHandExpression(), FIELD_NAME);
372+
var fieldValue = acceptAndYield(comparisonPredicate.getRightHandExpression(), FIELD_VALUE);
373+
374+
if (comparisonPredicate.getOperator() != EQUAL) {
375+
throw new FeatureNotSupportedException();
376+
}
377+
var filter = new AstFieldOperationFilter(
378+
new AstFilterFieldPath(fieldName), new AstComparisonFilterOperation(EQ, fieldValue));
379+
astVisitorValueHolder.yield(FILTER, filter);
380+
}
381+
382+
@Override
383+
public void visitSelectClause(SelectClause selectClause) {
384+
var projectStageSpecifications = new ArrayList<AstProjectStageSpecification>(
385+
selectClause.getSqlSelections().size());
386+
387+
for (SqlSelection sqlSelection : selectClause.getSqlSelections()) {
388+
if (sqlSelection.isVirtual()) {
389+
continue;
390+
}
391+
if (sqlSelection.getExpression() instanceof ColumnReference columnReference) {
392+
var columnName = acceptAndYield(columnReference, FIELD_NAME);
393+
projectStageSpecifications.add(include(columnName));
394+
} else {
395+
throw new FeatureNotSupportedException();
396+
}
397+
}
398+
astVisitorValueHolder.yield(PROJECT_STAGE_SPECIFICATIONS, projectStageSpecifications);
399+
}
400+
401+
@Override
402+
public void visitColumnReference(ColumnReference columnReference) {
403+
if (columnReference.isColumnExpressionFormula()) {
404+
throw new FeatureNotSupportedException();
405+
}
406+
astVisitorValueHolder.yield(FIELD_NAME, columnReference.getColumnExpression());
305407
}
306408

307409
@Override
@@ -329,11 +431,6 @@ public void visitQueryGroup(QueryGroup queryGroup) {
329431
throw new FeatureNotSupportedException();
330432
}
331433

332-
@Override
333-
public void visitQuerySpec(QuerySpec querySpec) {
334-
throw new FeatureNotSupportedException();
335-
}
336-
337434
@Override
338435
public void visitSortSpecification(SortSpecification sortSpecification) {
339436
throw new FeatureNotSupportedException();
@@ -344,21 +441,11 @@ public void visitOffsetFetchClause(QueryPart queryPart) {
344441
throw new FeatureNotSupportedException();
345442
}
346443

347-
@Override
348-
public void visitSelectClause(SelectClause selectClause) {
349-
throw new FeatureNotSupportedException();
350-
}
351-
352444
@Override
353445
public void visitSqlSelection(SqlSelection sqlSelection) {
354446
throw new FeatureNotSupportedException();
355447
}
356448

357-
@Override
358-
public void visitFromClause(FromClause fromClause) {
359-
throw new FeatureNotSupportedException();
360-
}
361-
362449
@Override
363450
public void visitTableGroup(TableGroup tableGroup) {
364451
throw new FeatureNotSupportedException();
@@ -369,11 +456,6 @@ public void visitTableGroupJoin(TableGroupJoin tableGroupJoin) {
369456
throw new FeatureNotSupportedException();
370457
}
371458

372-
@Override
373-
public void visitNamedTableReference(NamedTableReference namedTableReference) {
374-
throw new FeatureNotSupportedException();
375-
}
376-
377459
@Override
378460
public void visitValuesTableReference(ValuesTableReference valuesTableReference) {
379461
throw new FeatureNotSupportedException();
@@ -394,11 +476,6 @@ public void visitTableReferenceJoin(TableReferenceJoin tableReferenceJoin) {
394476
throw new FeatureNotSupportedException();
395477
}
396478

397-
@Override
398-
public void visitColumnReference(ColumnReference columnReference) {
399-
throw new FeatureNotSupportedException();
400-
}
401-
402479
@Override
403480
public void visitNestedColumnReference(NestedColumnReference nestedColumnReference) {
404481
throw new FeatureNotSupportedException();
@@ -609,11 +686,6 @@ public void visitThruthnessPredicate(ThruthnessPredicate thruthnessPredicate) {
609686
throw new FeatureNotSupportedException();
610687
}
611688

612-
@Override
613-
public void visitRelationalPredicate(ComparisonPredicate comparisonPredicate) {
614-
throw new FeatureNotSupportedException();
615-
}
616-
617689
@Override
618690
public void visitSelfRenderingPredicate(SelfRenderingPredicate selfRenderingPredicate) {
619691
throw new FeatureNotSupportedException();

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

+14-2
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,31 @@
1919
import static com.mongodb.hibernate.internal.MongoAssertions.assertNotNull;
2020
import static com.mongodb.hibernate.internal.MongoAssertions.fail;
2121

22-
import com.mongodb.hibernate.internal.translate.mongoast.AstNode;
2322
import com.mongodb.hibernate.internal.translate.mongoast.AstValue;
23+
import com.mongodb.hibernate.internal.translate.mongoast.command.AstCommand;
24+
import com.mongodb.hibernate.internal.translate.mongoast.command.aggregate.stage.AstProjectStageSpecification;
25+
import com.mongodb.hibernate.internal.translate.mongoast.filter.AstFilter;
2426
import java.lang.reflect.Modifier;
2527
import java.util.Collections;
2628
import java.util.IdentityHashMap;
29+
import java.util.List;
2730
import java.util.Map;
2831

2932
@SuppressWarnings("UnusedTypeParameter")
3033
final class AstVisitorValueDescriptor<T> {
3134

32-
static final AstVisitorValueDescriptor<AstNode> COLLECTION_MUTATION = new AstVisitorValueDescriptor<>();
35+
static final AstVisitorValueDescriptor<AstCommand> COLLECTION_MUTATION = new AstVisitorValueDescriptor<>();
36+
static final AstVisitorValueDescriptor<AstCommand> COLLECTION_AGGREGATE = new AstVisitorValueDescriptor<>();
37+
38+
static final AstVisitorValueDescriptor<String> COLLECTION_NAME = new AstVisitorValueDescriptor<>();
39+
40+
static final AstVisitorValueDescriptor<String> FIELD_NAME = new AstVisitorValueDescriptor<>();
3341
static final AstVisitorValueDescriptor<AstValue> FIELD_VALUE = new AstVisitorValueDescriptor<>();
3442

43+
static final AstVisitorValueDescriptor<List<AstProjectStageSpecification>> PROJECT_STAGE_SPECIFICATIONS =
44+
new AstVisitorValueDescriptor<>();
45+
static final AstVisitorValueDescriptor<AstFilter> FILTER = new AstVisitorValueDescriptor<>();
46+
3547
private static final Map<AstVisitorValueDescriptor<?>, String> CONSTANT_TOSTRING_CONTENT_MAP;
3648

3749
static {

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

+1-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,7 @@ public final class MongoTranslatorFactory implements SqlAstTranslatorFactory {
3030
@Override
3131
public SqlAstTranslator<JdbcOperationQuerySelect> buildSelectTranslator(
3232
SessionFactoryImplementor sessionFactoryImplementor, SelectStatement selectStatement) {
33-
// TODO-HIBERNATE-22 https://jira.mongodb.org/browse/HIBERNATE-22
34-
return new NoopSqlAstTranslator<>();
33+
return new SelectStatementMqlTranslator(sessionFactoryImplementor, selectStatement);
3534
}
3635

3736
@Override

0 commit comments

Comments
 (0)