Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* Executes an {@link MutableAggregateChange}.
*
* @author Jens Schauder
* @author Myeonghyeon Lee
* @since 2.0
*/
class AggregateChangeExecutor {
Expand Down Expand Up @@ -77,6 +78,10 @@ private void execute(DbAction<?> action, JdbcAggregateChangeExecutionContext exe
executionContext.executeDeleteRoot((DbAction.DeleteRoot<?>) action);
} else if (action instanceof DbAction.DeleteAllRoot) {
executionContext.executeDeleteAllRoot((DbAction.DeleteAllRoot<?>) action);
} else if (action instanceof DbAction.AcquireLockRoot) {
executionContext.executeAcquireLock((DbAction.AcquireLockRoot<?>) action);
} else if (action instanceof DbAction.AcquireLockAllRoot) {
executionContext.executeAcquireLockAllRoot((DbAction.AcquireLockAllRoot<?>) action);
} else {
throw new RuntimeException("unexpected action");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
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;

/**
* @author Jens Schauder
* @author Umut Erturk
* @author Myeonghyeon Lee
*/
class JdbcAggregateChangeExecutionContext {

Expand Down Expand Up @@ -164,6 +166,14 @@ <T> void executeMerge(DbAction.Merge<T> merge) {
}
}

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

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

private void add(DbActionExecutionResult result) {
results.put(result.getAction(), result);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
* @author Thomas Lang
* @author Christoph Strobl
* @author Milan Milanov
* @author Myeonghyeon Lee
*/
public class JdbcAggregateTemplate implements JdbcAggregateOperations {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.LockMode;

/**
* Delegates each methods to the {@link DataAccessStrategy}s passed to the constructor in turn until the first that does
Expand All @@ -33,6 +34,7 @@
* @author Mark Paluch
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
* @since 1.1
*/
public class CascadingDataAccessStrategy implements DataAccessStrategy {
Expand Down Expand Up @@ -115,6 +117,24 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
collectVoid(das -> das.deleteAll(propertyPath));
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockById(java.lang.Object, org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
collectVoid(das -> das.acquireLockById(id, lockMode, domainType));
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockAll(org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
collectVoid(das -> das.acquireLockAll(lockMode, domainType));
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.LockMode;
import org.springframework.lang.Nullable;

/**
Expand All @@ -33,6 +34,7 @@
* @author Jens Schauder
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
*/
public interface DataAccessStrategy extends RelationResolver {

Expand Down Expand Up @@ -129,6 +131,23 @@ public interface DataAccessStrategy extends RelationResolver {
*/
void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> propertyPath);

/**
* Acquire Lock
*
* @param id the id of the entity to load. Must not be {@code null}.
* @param lockMode the lock mode for select. Must not be {@code null}.
* @param domainType the domain type of the entity. Must not be {@code null}.
*/
<T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType);

/**
* Acquire Lock entities of the given domain type.
*
* @param lockMode the lock mode for select. Must not be {@code null}.
* @param domainType the domain type of the entity. Must not be {@code null}.
*/
<T> void acquireLockAll(LockMode lockMode, Class<T> domainType);

/**
* Counts the rows in the table representing the given domain type.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@
import static org.springframework.data.jdbc.core.convert.SqlGenerator.*;

import java.sql.JDBCType;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.dao.*;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.support.JdbcUtil;
Expand All @@ -41,7 +40,9 @@
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.LockMode;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
Expand All @@ -62,6 +63,7 @@
* @author Tom Hombergs
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
* @since 1.1
*/
public class DefaultDataAccessStrategy implements DataAccessStrategy {
Expand Down Expand Up @@ -237,6 +239,27 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
.update(sql(propertyPath.getBaseProperty().getOwner().getType()).createDeleteAllSql(propertyPath));
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockById(java.lang.Object, org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
String acquireLockByIdSql = sql(domainType).getAcquireLockById(lockMode);
SqlIdentifierParameterSource parameter = createIdParameterSource(id, domainType);
operations.queryForObject(acquireLockByIdSql, parameter, Object.class);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockAll(org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
String acquireLockAllSql = sql(domainType).getAcquireLockAll(lockMode);
operations.query(acquireLockAllSql, Collections.emptyMap(), new NoMappingResultSetExtractor());
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class)
Expand Down Expand Up @@ -582,4 +605,14 @@ public T getBean() {
return null;
}
}

/**
* The type No mapping result set extractor.
*/
static class NoMappingResultSetExtractor implements ResultSetExtractor<Object> {
@Override
public Object extractData(ResultSet resultSet) throws SQLException, DataAccessException {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.LockMode;
import org.springframework.util.Assert;

/**
Expand All @@ -28,6 +29,7 @@
* @author Jens Schauder
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
* @since 1.1
*/
public class DelegatingDataAccessStrategy implements DataAccessStrategy {
Expand Down Expand Up @@ -107,6 +109,24 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
delegate.deleteAll(propertyPath);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockById(java.lang.Object, org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
delegate.acquireLockById(id, lockMode, domainType);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockAll(org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
delegate.acquireLockAll(lockMode, domainType);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
* @author Tom Hombergs
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
*/
class SqlGenerator {

Expand Down Expand Up @@ -257,6 +258,26 @@ String getFindOne() {
return findOneSql.get();
}

/**
* Create a {@code SELECT count(id) FROM … WHERE :id = … (LOCK CLAUSE)} statement.
*
* @param lockMode Lock clause mode.
* @return the statement as a {@link String}. Guaranteed to be not {@literal null}.
*/
String getAcquireLockById(LockMode lockMode) {
return this.createAcquireLockById(lockMode);
}

/**
* Create a {@code SELECT count(id) FROM … (LOCK CLAUSE)} statement.
*
* @param lockMode Lock clause mode.
* @return the statement as a {@link String}. Guaranteed to be not {@literal null}.
*/
String getAcquireLockAll(LockMode lockMode) {
return this.createAcquireLockAll(lockMode);
}

/**
* Create a {@code INSERT INTO … (…) VALUES(…)} statement.
*
Expand Down Expand Up @@ -358,6 +379,33 @@ private String createFindOneSql() {
return render(select);
}

private String createAcquireLockById(LockMode lockMode) {

Table table = this.getTable();

Select select = StatementBuilder //
.select(getIdColumn()) //
.from(table) //
.where(getIdColumn().isEqualTo(getBindMarker(ID_SQL_PARAMETER))) //
.lock(lockMode) //
.build();

return render(select);
}

private String createAcquireLockAll(LockMode lockMode) {

Table table = this.getTable();

Select select = StatementBuilder //
.select(getIdColumn()) //
.from(table) //
.lock(lockMode) //
.build();

return render(select);
}

private String createFindAllSql() {
return render(selectBuilder().build());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jdbc.core.convert.CascadingDataAccessStrategy;
Expand All @@ -41,6 +42,7 @@
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.IdentifierProcessing;
import org.springframework.data.relational.core.sql.LockMode;
import org.springframework.data.relational.core.sql.SqlIdentifier;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.util.Assert;
Expand All @@ -60,6 +62,7 @@
* @author Mark Paluch
* @author Tyler Van Gorder
* @author Milan Milanov
* @author Myeonghyeon Lee
*/
public class MyBatisDataAccessStrategy implements DataAccessStrategy {

Expand Down Expand Up @@ -248,6 +251,34 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
sqlSession().delete(statement, parameter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockById(java.lang.Object, org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockById(Object id, LockMode lockMode, Class<T> domainType) {
String statement = namespace(domainType) + ".acquireLockById";
MyBatisContext parameter = new MyBatisContext(id, null, domainType, Collections.emptyMap());

long result = sqlSession().selectOne(statement, parameter);
if (result < 1) {
throw new EmptyResultDataAccessException(
String.format("The lock target does not exist. id: %s, statement: %s", id, statement), 1);
}
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#acquireLockAll(org.springframework.data.relational.core.sql.LockMode, java.lang.Class)
*/
@Override
public <T> void acquireLockAll(LockMode lockMode, Class<T> domainType) {
String statement = namespace(domainType) + ".acquireLockAll";
MyBatisContext parameter = new MyBatisContext(null, null, domainType, Collections.emptyMap());

sqlSession().selectOne(statement, parameter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class)
Expand Down
Loading