Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
target/
.idea/
.vscode/
.settings/
*.iml
.flattened-pom.xml
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1980-jspecify-SNAPSHOT</version>
<packaging>pom</packaging>

<name>Spring Data Relational Parent</name>
Expand Down
2 changes: 1 addition & 1 deletion spring-data-jdbc-distribution/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1980-jspecify-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
4 changes: 2 additions & 2 deletions spring-data-jdbc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<modelVersion>4.0.0</modelVersion>

<artifactId>spring-data-jdbc</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1980-jspecify-SNAPSHOT</version>

<name>Spring Data JDBC</name>
<description>Spring Data module for JDBC repositories.</description>
Expand All @@ -15,7 +15,7 @@
<parent>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-relational-parent</artifactId>
<version>4.0.0-SNAPSHOT</version>
<version>4.0.0-1980-jspecify-SNAPSHOT</version>
</parent>

<properties>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import java.util.Arrays;

import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.MemberCategory;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.RuntimeHintsRegistrar;
Expand All @@ -30,7 +31,6 @@
import org.springframework.data.relational.core.mapping.event.BeforeConvertCallback;
import org.springframework.data.relational.core.mapping.event.BeforeDeleteCallback;
import org.springframework.data.relational.core.mapping.event.BeforeSaveCallback;
import org.springframework.lang.Nullable;

/**
* {@link RuntimeHintsRegistrar} for JDBC.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,12 @@
*/
package org.springframework.data.jdbc.core;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
Expand All @@ -48,7 +40,6 @@
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.LockMode;
import org.springframework.data.util.Pair;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
Expand Down Expand Up @@ -82,18 +73,18 @@ class JdbcAggregateChangeExecutionContext {

<T> void executeInsertRoot(DbAction.InsertRoot<T> insert) {

Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty(),
insert.getIdValueSource());
Object id = accessStrategy.insert(insert.entity(), insert.entityType(), Identifier.empty(),
insert.idValueSource());
add(new DbActionExecutionResult(insert, id));
}

<T> void executeBatchInsertRoot(DbAction.BatchInsertRoot<T> batchInsertRoot) {

List<DbAction.InsertRoot<T>> inserts = batchInsertRoot.getActions();
List<InsertSubject<T>> insertSubjects = inserts.stream()
.map(insert -> InsertSubject.describedBy(insert.getEntity(), Identifier.empty())).collect(Collectors.toList());
.map(insert -> InsertSubject.describedBy(insert.entity(), Identifier.empty())).collect(Collectors.toList());

Object[] ids = accessStrategy.insert(insertSubjects, batchInsertRoot.getEntityType(),
Object[] ids = accessStrategy.insert(insertSubjects, batchInsertRoot.entityType(),
batchInsertRoot.getBatchValue());

for (int i = 0; i < inserts.size(); i++) {
Expand All @@ -104,19 +95,19 @@ <T> void executeBatchInsertRoot(DbAction.BatchInsertRoot<T> batchInsertRoot) {
<T> void executeInsert(DbAction.Insert<T> insert) {

Identifier parentKeys = getParentKeys(insert, converter);
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), parentKeys,
insert.getIdValueSource());
Object id = accessStrategy.insert(insert.entity(), insert.entityType(), parentKeys,
insert.idValueSource());
add(new DbActionExecutionResult(insert, id));
}

<T> void executeBatchInsert(DbAction.BatchInsert<T> batchInsert) {

List<DbAction.Insert<T>> inserts = batchInsert.getActions();
List<InsertSubject<T>> insertSubjects = inserts.stream()
.map(insert -> InsertSubject.describedBy(insert.getEntity(), getParentKeys(insert, converter)))
.map(insert -> InsertSubject.describedBy(insert.entity(), getParentKeys(insert, converter)))
.collect(Collectors.toList());

Object[] ids = accessStrategy.insert(insertSubjects, batchInsert.getEntityType(), batchInsert.getBatchValue());
Object[] ids = accessStrategy.insert(insertSubjects, batchInsert.entityType(), batchInsert.getBatchValue());

for (int i = 0; i < inserts.size(); i++) {
add(new DbActionExecutionResult(inserts.get(i), ids.length > 0 ? ids[i] : null));
Expand All @@ -135,46 +126,46 @@ <T> void executeUpdateRoot(DbAction.UpdateRoot<T> update) {

<T> void executeDeleteRoot(DbAction.DeleteRoot<T> delete) {

if (delete.getPreviousVersion() != null) {
accessStrategy.deleteWithVersion(delete.getId(), delete.getEntityType(), delete.getPreviousVersion());
if (delete.previousVersion() != null) {
accessStrategy.deleteWithVersion(delete.id(), delete.entityType(), delete.previousVersion());
} else {
accessStrategy.delete(delete.getId(), delete.getEntityType());
accessStrategy.delete(delete.id(), delete.entityType());
}
}

<T> void executeBatchDeleteRoot(DbAction.BatchDeleteRoot<T> batchDelete) {

List<Object> rootIds = batchDelete.getActions().stream().map(DbAction.DeleteRoot::getId).toList();
accessStrategy.delete(rootIds, batchDelete.getEntityType());
List<Object> rootIds = batchDelete.getActions().stream().map(DbAction.DeleteRoot::id).toList();
accessStrategy.delete(rootIds, batchDelete.entityType());
}

<T> void executeDelete(DbAction.Delete<T> delete) {

accessStrategy.delete(delete.getRootId(), delete.getPropertyPath());
accessStrategy.delete(delete.rootId(), delete.propertyPath());
}

<T> void executeBatchDelete(DbAction.BatchDelete<T> batchDelete) {

List<Object> rootIds = batchDelete.getActions().stream().map(DbAction.Delete::getRootId).toList();
List<Object> rootIds = batchDelete.getActions().stream().map(DbAction.Delete::rootId).toList();
accessStrategy.delete(rootIds, batchDelete.getBatchValue());
}

<T> void executeDeleteAllRoot(DbAction.DeleteAllRoot<T> deleteAllRoot) {

accessStrategy.deleteAll(deleteAllRoot.getEntityType());
accessStrategy.deleteAll(deleteAllRoot.entityType());
}

<T> void executeDeleteAll(DbAction.DeleteAll<T> delete) {

accessStrategy.deleteAll(delete.getPropertyPath());
accessStrategy.deleteAll(delete.propertyPath());
}

<T> void executeAcquireLock(DbAction.AcquireLockRoot<T> acquireLock) {
accessStrategy.acquireLockById(acquireLock.getId(), LockMode.PESSIMISTIC_WRITE, acquireLock.getEntityType());
accessStrategy.acquireLockById(acquireLock.getId(), LockMode.PESSIMISTIC_WRITE, acquireLock.entityType());
}

<T> void executeAcquireLockAllRoot(DbAction.AcquireLockAllRoot<T> acquireLock) {
accessStrategy.acquireLockAll(LockMode.PESSIMISTIC_WRITE, acquireLock.getEntityType());
accessStrategy.acquireLockAll(LockMode.PESSIMISTIC_WRITE, acquireLock.entityType());
}

private void add(DbActionExecutionResult result) {
Expand All @@ -185,11 +176,11 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert

Object id = getParentId(action);

AggregatePath aggregatePath = context.getAggregatePath(action.getPropertyPath());
AggregatePath aggregatePath = context.getAggregatePath(action.propertyPath());
JdbcIdentifierBuilder identifier = JdbcIdentifierBuilder //
.forBackReferences(converter, aggregatePath, getIdMapper(id, aggregatePath, converter));

for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers()
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.qualifiers()
.entrySet()) {
identifier = identifier.withQualifier(context.getAggregatePath(qualifier.getKey()), qualifier.getValue());
}
Expand All @@ -200,21 +191,21 @@ private Identifier getParentKeys(DbAction.WithDependingOn<?> action, JdbcConvert
static Function<AggregatePath, Object> getIdMapper(Object idValue, AggregatePath path, JdbcConverter converter) {

RelationalPersistentProperty idProperty = path.getIdDefiningParentPath().getRequiredIdProperty();
RelationalPersistentEntity<?> entity = converter.getMappingContext()
.getPersistentEntity(idProperty);
RelationalPersistentEntity<?> entity = converter.getMappingContext().getPersistentEntity(idProperty);

if (entity == null) {
return aggregatePath -> idValue;
}

PersistentPropertyPathAccessor<Object> propertyPathAccessor = entity.getPropertyPathAccessor(idValue);
return aggregatePath -> propertyPathAccessor.getProperty(aggregatePath.getSubPathBasedOn(idProperty.getActualType()).getRequiredPersistentPropertyPath());
return aggregatePath -> propertyPathAccessor
.getProperty(aggregatePath.getSubPathBasedOn(idProperty.getActualType()).getRequiredPersistentPropertyPath());
}

private Object getParentId(DbAction.WithDependingOn<?> action) {

DbAction.WithEntity<?> idOwningAction = getIdOwningAction(action,
context.getAggregatePath(action.getPropertyPath()).getIdDefiningParentPath());
context.getAggregatePath(action.propertyPath()).getIdDefiningParentPath());

return getPotentialGeneratedIdFrom(idOwningAction);
}
Expand All @@ -229,16 +220,16 @@ private DbAction.WithEntity<?> getIdOwningAction(DbAction.WithEntity<?> action,
return action;
}

if (idPath.equals(context.getAggregatePath(withDependingOn.getPropertyPath()))) {
if (idPath.equals(context.getAggregatePath(withDependingOn.propertyPath()))) {
return action;
}

return getIdOwningAction(withDependingOn.getDependingOn(), idPath);
return getIdOwningAction(withDependingOn.dependingOn(), idPath);
}

private Object getPotentialGeneratedIdFrom(DbAction.WithEntity<?> idOwningAction) {

if (IdValueSource.GENERATED.equals(idOwningAction.getIdValueSource())) {
if (IdValueSource.GENERATED.equals(idOwningAction.idValueSource())) {

DbActionExecutionResult dbActionExecutionResult = results.get(idOwningAction);
Object generatedId = Optional.ofNullable(dbActionExecutionResult) //
Expand All @@ -255,8 +246,8 @@ private Object getPotentialGeneratedIdFrom(DbAction.WithEntity<?> idOwningAction

private Object getIdFrom(DbAction.WithEntity<?> idOwningAction) {

RelationalPersistentEntity<?> persistentEntity = getRequiredPersistentEntity(idOwningAction.getEntityType());
Object identifier = persistentEntity.getIdentifierAccessor(idOwningAction.getEntity()).getIdentifier();
RelationalPersistentEntity<?> persistentEntity = getRequiredPersistentEntity(idOwningAction.entityType());
Object identifier = persistentEntity.getIdentifierAccessor(idOwningAction.entity()).getIdentifier();

Assert.state(identifier != null, () -> "Couldn't obtain a required id value for " + persistentEntity);

Expand Down Expand Up @@ -290,12 +281,12 @@ <T> List<T> populateIdsIfNecessary() {
Pair<?, ?> qualifier = insert.getQualifier();
Object qualifierValue = qualifier == null ? null : qualifier.getSecond();

if (newEntity != action.getEntity()) {
if (newEntity != action.entity()) {

cascadingValues.stage(insert.getDependingOn(), insert.getPropertyPath(), qualifierValue, newEntity);
} else if (insert.getPropertyPath().getLeafProperty().isCollectionLike()) {
cascadingValues.stage(insert.dependingOn(), insert.propertyPath(), qualifierValue, newEntity);
} else if (insert.propertyPath().getLeafProperty().isCollectionLike()) {

cascadingValues.gather(insert.getDependingOn(), insert.getPropertyPath(), qualifierValue, newEntity);
cascadingValues.gather(insert.dependingOn(), insert.propertyPath(), qualifierValue, newEntity);
}
}
}
Expand All @@ -315,14 +306,14 @@ <T> List<T> populateIdsIfNecessary() {
private <S> Object setIdAndCascadingProperties(DbAction.WithEntity<S> action, @Nullable Object generatedId,
StagedValues cascadingValues) {

S originalEntity = action.getEntity();
S originalEntity = action.entity();

RelationalPersistentEntity<S> persistentEntity = (RelationalPersistentEntity<S>) context
.getRequiredPersistentEntity(action.getEntityType());
.getRequiredPersistentEntity(action.entityType());
PersistentPropertyPathAccessor<S> propertyAccessor = converter.getPropertyAccessor(persistentEntity,
originalEntity);

if (IdValueSource.GENERATED.equals(action.getIdValueSource())) {
if (IdValueSource.GENERATED.equals(action.idValueSource())) {
propertyAccessor.setProperty(persistentEntity.getRequiredIdProperty(), generatedId);
}

Expand All @@ -337,7 +328,7 @@ private <S> Object setIdAndCascadingProperties(DbAction.WithEntity<S> action, @N
private PersistentPropertyPath<?> getRelativePath(DbAction<?> action, PersistentPropertyPath<?> pathToValue) {

if (action instanceof DbAction.Insert insert) {
return pathToValue.getExtensionForBaseOf(insert.getPropertyPath());
return pathToValue.getExtensionForBaseOf(insert.propertyPath());
}

if (action instanceof DbAction.InsertRoot) {
Expand All @@ -358,10 +349,10 @@ private <T> RelationalPersistentEntity<T> getRequiredPersistentEntity(Class<T> t

private <T> void updateWithoutVersion(DbAction.UpdateRoot<T> update) {

if (!accessStrategy.update(update.getEntity(), update.getEntityType())) {
if (!accessStrategy.update(update.entity(), update.entityType())) {

throw new IncorrectUpdateSemanticsDataAccessException(
String.format(UPDATE_FAILED, update.getEntity(), getIdFrom(update)));
String.format(UPDATE_FAILED, update.entity(), getIdFrom(update)));
}
}

Expand All @@ -370,9 +361,9 @@ private <T> void updateWithVersion(DbAction.UpdateRoot<T> update) {
Number previousVersion = update.getPreviousVersion();
Assert.notNull(previousVersion, "The root aggregate cannot be updated because the version property is null");

if (!accessStrategy.updateWithVersion(update.getEntity(), update.getEntityType(), previousVersion)) {
if (!accessStrategy.updateWithVersion(update.entity(), update.entityType(), previousVersion)) {

throw new OptimisticLockingFailureException(String.format(UPDATE_FAILED_OPTIMISTIC_LOCKING, update.getEntity()));
throw new OptimisticLockingFailureException(String.format(UPDATE_FAILED_OPTIMISTIC_LOCKING, update.entity()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Optional;
import java.util.stream.Stream;

import org.jspecify.annotations.Nullable;
import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
Expand All @@ -27,7 +28,6 @@
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.relational.core.query.Query;
import org.springframework.lang.Nullable;

/**
* Specifies operations one can perform on a database, based on an <em>Domain Type</em>.
Expand Down Expand Up @@ -171,8 +171,8 @@ public interface JdbcAggregateOperations {
<T> List<T> findAllById(Iterable<?> ids, Class<T> domainType);

/**
* Loads all entities that match one of the ids passed as an argument to a {@link Stream}.
* It is not guaranteed that the number of ids passed in matches the number of entities returned.
* Loads all entities that match one of the ids passed as an argument to a {@link Stream}. It is not guaranteed that
* the number of ids passed in matches the number of entities returned.
*
* @param ids the Ids of the entities to load. Must not be {@code null}.
* @param domainType the type of entities to load. Must not be {@code null}.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.jspecify.annotations.Nullable;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
Expand Down Expand Up @@ -55,7 +56,6 @@
import org.springframework.data.relational.core.mapping.event.*;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

Expand Down Expand Up @@ -305,7 +305,7 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
}

@Override
public <T> T findById(Object id, Class<T> domainType) {
public <T> @Nullable T findById(Object id, Class<T> domainType) {

Assert.notNull(id, "Id must not be null");
Assert.notNull(domainType, "Domain type must not be null");
Expand Down
Loading