DATAJDBC-219 - Polishing.

DeleteWithVersion doesn't require an entity anymore.
Added the `@author` and `@since` tags where they were missing.
Formatting.
Added documentation.

Original pull request: #166.
This commit is contained in:
Jens Schauder
2019-11-29 13:45:50 +01:00
parent f7a04dcc2b
commit ca2d2182d2
19 changed files with 190 additions and 157 deletions

View File

@@ -80,7 +80,6 @@ class AggregateChangeExecutor {
}
@SuppressWarnings("unchecked")
@Nullable
private <T> T populateRootVersionIfNecessary(T newRoot, List<DbAction<?>> actions) {
// Does the root entity have a version attribute?
@@ -98,12 +97,13 @@ class AggregateChangeExecutor {
// This really should never happen.
return newRoot;
}
DbAction.WithVersion<T> versionAction = (DbAction.WithVersion<T>) rootAction.get();
DbAction.WithVersion versionAction = (DbAction.WithVersion) rootAction.get();
return RelationalEntityVersionUtils.setVersionNumberOnEntity(newRoot,
versionAction.getNextVersion(), persistentEntity, converter);
return RelationalEntityVersionUtils.setVersionNumberOnEntity(newRoot, versionAction.getNextVersion(),
persistentEntity, converter);
}
@SuppressWarnings("unchecked")
@Nullable
private <T> T populateIdsIfNecessary(List<DbAction<?>> actions) {
@@ -145,7 +145,6 @@ class AggregateChangeExecutor {
return newRoot;
}
@SuppressWarnings("unchecked")
private <S> Object setIdAndCascadingProperties(DbAction.WithGeneratedId<S> action, @Nullable Object generatedId,
AggregateChangeExecutor.StagedValues cascadingValues) {

View File

@@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor;
import java.util.Map;
import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.jdbc.core.convert.DataAccessStrategy;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.conversion.DbAction;
@@ -55,6 +56,7 @@ import org.springframework.util.Assert;
class DefaultJdbcInterpreter implements Interpreter {
public static final String UPDATE_FAILED = "Failed to update entity [%s]. Id [%s] not found in database.";
public static final String UPDATE_FAILED_OPTIMISTIC_LOCKING = "Failed to update entity [%s]. The entity was updated since it was rea or it isn't in the database at all.";
private final RelationalConverter converter;
private final RelationalMappingContext context;
private final DataAccessStrategy accessStrategy;
@@ -65,15 +67,11 @@ class DefaultJdbcInterpreter implements Interpreter {
*/
@Override
public <T> void interpret(Insert<T> insert) {
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), getParentKeys(insert));
insert.setGeneratedId(id);
}
@SuppressWarnings("unchecked")
private <T> RelationalPersistentEntity<T> getRequiredPersistentEntity(Class<T> type) {
return (RelationalPersistentEntity<T>) context.getRequiredPersistentEntity(type);
}
/*
* (non-Javadoc)
* @see org.springframework.data.relational.core.conversion.Interpreter#interpret(org.springframework.data.relational.core.conversion.DbAction.InsertRoot)
@@ -83,22 +81,17 @@ class DefaultJdbcInterpreter implements Interpreter {
RelationalPersistentEntity<T> persistentEntity = getRequiredPersistentEntity(insert.getEntityType());
Object id;
if (persistentEntity.hasVersionProperty()) {
// The interpreter is responsible for setting the initial version on the entity prior to calling insert.
Number version = RelationalEntityVersionUtils.getVersionNumberFromEntity(insert.getEntity(), persistentEntity,
converter);
if (version != null && version.longValue() > 0) {
throw new IllegalArgumentException("The entity cannot be inserted because it already has a version.");
}
T rootEntity = RelationalEntityVersionUtils.setVersionNumberOnEntity(insert.getEntity(), 1, persistentEntity,
converter);
Object id = accessStrategy.insert(rootEntity, insert.getEntityType(), Identifier.empty());
id = accessStrategy.insert(rootEntity, insert.getEntityType(), Identifier.empty());
insert.setNextVersion(1);
insert.setGeneratedId(id);
} else {
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty());
insert.setGeneratedId(id);
id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty());
}
insert.setGeneratedId(id);
}
/*
@@ -125,23 +118,25 @@ class DefaultJdbcInterpreter implements Interpreter {
RelationalPersistentEntity<T> persistentEntity = getRequiredPersistentEntity(update.getEntityType());
if (persistentEntity.hasVersionProperty()) {
// If the root aggregate has a version property, increment it.
Number previousVersion = RelationalEntityVersionUtils.getVersionNumberFromEntity(update.getEntity(),
persistentEntity, converter);
Assert.notNull(previousVersion, "The root aggregate cannot be updated because the version property is null.");
T rootEntity = RelationalEntityVersionUtils.setVersionNumberOnEntity(update.getEntity(),
previousVersion.longValue() + 1, persistentEntity,
converter);
previousVersion.longValue() + 1, persistentEntity, converter);
if (accessStrategy.updateWithVersion(rootEntity, update.getEntityType(), previousVersion)) {
// Successful update, set the in-memory version on the action.
update.setNextVersion(previousVersion);
} else {
throw new IncorrectUpdateSemanticsDataAccessException(
String.format(UPDATE_FAILED, update.getEntity(), getIdFrom(update)));
}
if (accessStrategy.updateWithVersion(rootEntity, update.getEntityType(), previousVersion)) {
// Successful update, set the in-memory version on the action.
update.setNextVersion(previousVersion);
} else {
throw new OptimisticLockingFailureException(
String.format(UPDATE_FAILED_OPTIMISTIC_LOCKING, update.getEntity()));
}
} else {
if (!accessStrategy.update(update.getEntity(), update.getEntityType())) {
throw new IncorrectUpdateSemanticsDataAccessException(
@@ -179,10 +174,12 @@ class DefaultJdbcInterpreter implements Interpreter {
@Override
public <T> void interpret(DeleteRoot<T> delete) {
if (delete.getEntity() != null) {
if (delete.getPreviousVersion() != null) {
RelationalPersistentEntity<T> persistentEntity = getRequiredPersistentEntity(delete.getEntityType());
if (persistentEntity.hasVersionProperty()) {
accessStrategy.deleteWithVersion(delete.getEntity(), delete.getEntityType());
accessStrategy.deleteWithVersion(delete.getId(), delete.getEntityType(), delete.getPreviousVersion());
return;
}
}
@@ -274,4 +271,9 @@ class DefaultJdbcInterpreter implements Interpreter {
return identifier;
}
@SuppressWarnings("unchecked")
private <T> RelationalPersistentEntity<T> getRequiredPersistentEntity(Class<T> type) {
return (RelationalPersistentEntity<T>) context.getRequiredPersistentEntity(type);
}
}

View File

@@ -31,6 +31,7 @@ import org.springframework.data.relational.domain.Identifier;
*
* @author Jens Schauder
* @author Mark Paluch
* @author Tyler Van Gorder
* @since 1.1
*/
public class CascadingDataAccessStrategy implements DataAccessStrategy {
@@ -91,8 +92,8 @@ public class CascadingDataAccessStrategy implements DataAccessStrategy {
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteInstance(java.lang.Object, java.lang.Class)
*/
@Override
public <T> void deleteWithVersion(T instance, Class<T> domainType) {
collectVoid(das -> das.deleteWithVersion(instance, domainType));
public <T> void deleteWithVersion(Object id, Class<T> domainType, Number previousVersion) {
collectVoid(das -> das.deleteWithVersion(id, domainType, previousVersion));
}
/*

View File

@@ -17,6 +17,7 @@ package org.springframework.data.jdbc.core.convert;
import java.util.Map;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
import org.springframework.data.mapping.PersistentPropertyPath;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@@ -75,7 +76,7 @@ public interface DataAccessStrategy extends RelationResolver {
<T> boolean update(T instance, Class<T> domainType);
/**
* Updates the data of a single entity in the database and enforce optimistic record locking using the previousVersion
* Updates the data of a single entity in the database and enforce optimistic record locking using the {@code previousVersion}
* property. Referenced entities don't get handled.
* <P>
* The statement will be of the form : {@code UPDATE … SET … WHERE ID = :id and VERSION_COLUMN = :previousVersion }
@@ -86,6 +87,8 @@ public interface DataAccessStrategy extends RelationResolver {
* @param previousVersion The previous version assigned to the instance being saved.
* @param <T> the type of the instance to save.
* @return whether the update actually updated a row.
* @throws OptimisticLockingFailureException if the update fails to update at least one row assuming the the optimistic locking version check failed.
* @since 2.0
*/
<T> boolean updateWithVersion(T instance, Class<T> domainType, Number previousVersion);
@@ -109,8 +112,11 @@ public interface DataAccessStrategy extends RelationResolver {
* @param id the id of the row to be deleted. Must not be {@code null}.
* @param domainType the type of entity to be deleted. Implicitly determines the table to operate on. Must not be
* {@code null}.
* @param previousVersion The previous version assigned to the instance being saved.
* @throws OptimisticLockingFailureException if the update fails to update at least one row assuming the the optimistic locking version check failed.
* @since 2.0
*/
<T> void deleteWithVersion(T instance, Class<T> domainType);
<T> void deleteWithVersion(Object id, Class<T> domainType, Number previousVersion);
/**
* Deletes all entities reachable via {@literal propertyPath} from the instance identified by {@literal rootId}.

View File

@@ -184,23 +184,17 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteInstance(java.lang.Object, java.lang.Class)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteInstance(java.lang.Object, java.lang.Class, java.lang.Number)
*/
@Override
public <T> void deleteWithVersion(T instance, Class<T> domainType) {
public <T> void deleteWithVersion(Object id, Class<T> domainType, Number previousVersion) {
Assert.notNull(id, "Id must not be null.");
RelationalPersistentEntity<T> persistentEntity = getRequiredPersistentEntity(domainType);
Object id = getIdValueOrNull(instance, persistentEntity);
Assert.notNull(id, "Cannot delete an instance without it's ID being populated.");
if (!persistentEntity.hasVersionProperty()) {
delete(id, domainType);
return;
}
Number oldVersion = RelationalEntityVersionUtils.getVersionNumberFromEntity(instance, persistentEntity, converter);
MapSqlParameterSource parameterSource = createIdParameterSource(id, domainType);
parameterSource.addValue(VERSION_SQL_PARAMETER_NAME, oldVersion);
parameterSource.addValue(VERSION_SQL_PARAMETER_NAME, previousVersion);
int affectedRows = operations.update(sql(domainType).getDeleteByIdAndVersion(), parameterSource);
if (affectedRows == 0) {

View File

@@ -27,6 +27,7 @@ import org.springframework.util.Assert;
* cyclic dependencies.
*
* @author Jens Schauder
* @author Tyler Van Gorder
* @since 1.1
*/
public class DelegatingDataAccessStrategy implements DataAccessStrategy {
@@ -89,11 +90,11 @@ public class DelegatingDataAccessStrategy implements DataAccessStrategy {
/*
* (non-Javadoc)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteWithVersion(java.lang.Object, java.lang.Class)
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteWithVersion(java.lang.Object, java.lang.Class, Number)
*/
@Override
public <T> void deleteWithVersion(T instance, Class<T> domainType) {
delegate.deleteWithVersion(instance, domainType);
public <T> void deleteWithVersion(Object id, Class<T> domainType, Number previousVersion) {
delegate.deleteWithVersion(id, domainType, previousVersion);
}
/*

View File

@@ -26,6 +26,7 @@ import org.springframework.data.relational.core.sql.Table;
*
* @author Jens Schauder
* @author Mark Paluch
* @author Tyler Van Gorder
* @since 1.1
*/
class SqlContext {
@@ -43,10 +44,7 @@ class SqlContext {
}
Column getVersionColumn() {
if (!entity.hasVersionProperty()) {
return null;
}
return table.column(entity.getVersionProperty().getColumnName());
return table.column(entity.getRequiredVersionProperty().getColumnName());
}
Table getTable() {

View File

@@ -37,24 +37,7 @@ import org.springframework.data.relational.core.mapping.PersistentPropertyPathEx
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
import org.springframework.data.relational.core.sql.AssignValue;
import org.springframework.data.relational.core.sql.Assignments;
import org.springframework.data.relational.core.sql.BindMarker;
import org.springframework.data.relational.core.sql.Column;
import org.springframework.data.relational.core.sql.Condition;
import org.springframework.data.relational.core.sql.Delete;
import org.springframework.data.relational.core.sql.DeleteBuilder;
import org.springframework.data.relational.core.sql.Expression;
import org.springframework.data.relational.core.sql.Expressions;
import org.springframework.data.relational.core.sql.Functions;
import org.springframework.data.relational.core.sql.Insert;
import org.springframework.data.relational.core.sql.InsertBuilder;
import org.springframework.data.relational.core.sql.SQL;
import org.springframework.data.relational.core.sql.Select;
import org.springframework.data.relational.core.sql.SelectBuilder;
import org.springframework.data.relational.core.sql.StatementBuilder;
import org.springframework.data.relational.core.sql.Table;
import org.springframework.data.relational.core.sql.Update;
import org.springframework.data.relational.core.sql.*;
import org.springframework.data.relational.core.sql.render.SqlRenderer;
import org.springframework.data.relational.domain.Identifier;
import org.springframework.data.util.Lazy;
@@ -501,25 +484,20 @@ class SqlGenerator {
}
private String createUpdateSql() {
Table table = getTable();
List<AssignValue> assignments = columns.getUpdateableColumns() //
.stream() //
.map(columnName -> Assignments.value( //
table.column(columnName), //
getBindMarker(columnName))) //
.collect(Collectors.toList());
Update update = Update.builder() //
.table(table) //
.set(assignments) //
.where(getIdColumn().isEqualTo(getBindMarker(entity.getIdColumn()))).build();
return render(update);
return render(createBaseUpdate().build());
}
private String createUpdateWithVersionSql() {
Update update = createBaseUpdate() //
.and(getVersionColumn().isEqualTo(SQL.bindMarker(":" + VERSION_SQL_PARAMETER_NAME))) //
.build();
return render(update);
}
private UpdateBuilder.UpdateWhereAndOr createBaseUpdate() {
Table table = getTable();
List<AssignValue> assignments = columns.getUpdateableColumns() //
@@ -529,37 +507,27 @@ class SqlGenerator {
getBindMarker(columnName))) //
.collect(Collectors.toList());
Update update = null;
update = Update.builder() //
return Update.builder() //
.table(table) //
.set(assignments) //
.where(getIdColumn().isEqualTo(getBindMarker(entity.getIdColumn()))) //
.and(getVersionColumn().isEqualTo(SQL.bindMarker(":" + VERSION_SQL_PARAMETER_NAME))) //
.build();
return render(update);
.where(getIdColumn().isEqualTo(getBindMarker(entity.getIdColumn())));
}
private String createDeleteSql() {
return render(createBaseDeleteById(getTable()).build());
}
Table table = getTable();
private String createDeleteByIdAndVersionSql() {
Delete delete = Delete.builder().from(table).where(getIdColumn().isEqualTo(SQL.bindMarker(":id"))) //
Delete delete = createBaseDeleteById(getTable()) //
.and(getVersionColumn().isEqualTo(SQL.bindMarker(":" + VERSION_SQL_PARAMETER_NAME))) //
.build();
return render(delete);
}
private String createDeleteByIdAndVersionSql() {
Table table = getTable();
Delete delete = Delete.builder() //
.from(table) //
.where(getIdColumn().isEqualTo(SQL.bindMarker(":id"))) //
.and(getVersionColumn().isEqualTo(SQL.bindMarker(":" + VERSION_SQL_PARAMETER_NAME))) //
.build();
return render(delete);
private DeleteBuilder.DeleteWhereAndOr createBaseDeleteById(Table table) {
return Delete.builder().from(table).where(getIdColumn().isEqualTo(SQL.bindMarker(":id")));
}
private String createDeleteByPathAndCriteria(PersistentPropertyPathExtension path,

View File

@@ -174,11 +174,9 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
@Override
public <S> boolean updateWithVersion(S instance, Class<S> domainType, Number previousVersion) {
Map<String, Object> additionalValues = new HashMap<>();
additionalValues.put(VERSION_SQL_PARAMETER_NAME_OLD, previousVersion);
return sqlSession().update(namespace(domainType) + ".updateWithVersion",
new MyBatisContext(null, instance, domainType, additionalValues)) != 0;
new MyBatisContext(null, instance, domainType, Collections.singletonMap(VERSION_SQL_PARAMETER_NAME_OLD, previousVersion))) != 0;
}
/*
@@ -197,10 +195,10 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteInstance(java.lang.Object, java.lang.Class)
*/
@Override
public <T> void deleteWithVersion(T instance, Class<T> domainType) {
public <T> void deleteWithVersion(Object id, Class<T> domainType, Number previousVersion) {
sqlSession().delete(namespace(domainType) + ".deleteWithVersion",
new MyBatisContext(null, instance, domainType, Collections.emptyMap()));
new MyBatisContext(id, null, domainType, Collections.singletonMap(VERSION_SQL_PARAMETER_NAME_OLD, previousVersion)));
}
/*

View File

@@ -48,6 +48,7 @@ import org.springframework.data.relational.domain.Identifier;
* @author Jens Schauder
* @author Mark Paluch
* @author Myeonghyeon Lee
* @author Tyler Van Gorder
*/
public class DefaultJdbcInterpreterUnitTests {

View File

@@ -15,12 +15,8 @@
*/
package org.springframework.data.jdbc.core;
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -642,27 +638,29 @@ public class JdbcAggregateTemplateIntegrationTests {
@Test // DATAJDBC-219 Test that immutable version attribute works as expected.
public void saveAndUpdateAggregateWithImmutableVersion() {
AggregateWithImmutableVersion aggregate = new AggregateWithImmutableVersion(null, null);
aggregate = template.save(aggregate);
Long id = aggregate.getId();
AggregateWithImmutableVersion reloadedAggregate = template.findById(id, aggregate.getClass());
assertThat(reloadedAggregate.getVersion()).isEqualTo(1L)
.withFailMessage("version field should initially have the value 1");
reloadedAggregate = template.save(reloadedAggregate);
assertThat(reloadedAggregate.getVersion()).describedAs("version field should initially have the value 1")
.isEqualTo(1L);
template.save(reloadedAggregate);
AggregateWithImmutableVersion updatedAggregate = template.findById(id, aggregate.getClass());
assertThat(updatedAggregate.getVersion()).isEqualTo(2L)
.withFailMessage("version field should increment by one with each save");
assertThat(updatedAggregate.getVersion()).describedAs("version field should increment by one with each save")
.isEqualTo(2L);
assertThatThrownBy(() -> template.save(new AggregateWithImmutableVersion(id, 1L)))
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class)
.withFailMessage("saving an aggregate with an outdated version should raise an exception");
.describedAs("saving an aggregate with an outdated version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
assertThatThrownBy(() -> template.save(new AggregateWithImmutableVersion(id, 3L)))
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class)
.withFailMessage("saving an aggregate with a future version should raise an exception");
.describedAs("saving an aggregate with a future version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
}
@Test // DATAJDBC-219 Test that a delete with a version attribute works as expected.
@@ -671,26 +669,26 @@ public class JdbcAggregateTemplateIntegrationTests {
AggregateWithImmutableVersion aggregate = new AggregateWithImmutableVersion(null, null);
aggregate = template.save(aggregate);
//Should have an ID and a version of 1.
// Should have an ID and a version of 1.
final Long id = aggregate.getId();
assertThatThrownBy(() -> template.delete(new AggregateWithImmutableVersion(id, 0L), AggregateWithImmutableVersion.class))
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class)
.withFailMessage("deleting an aggregate with an outdated version should raise an exception");
assertThatThrownBy(
() -> template.delete(new AggregateWithImmutableVersion(id, 0L), AggregateWithImmutableVersion.class))
.describedAs("deleting an aggregate with an outdated version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
assertThatThrownBy(() -> template.delete(new AggregateWithImmutableVersion(id, 3L), AggregateWithImmutableVersion.class))
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class)
.withFailMessage("deleting an aggregate with a future version should raise an exception");
assertThatThrownBy(
() -> template.delete(new AggregateWithImmutableVersion(id, 3L), AggregateWithImmutableVersion.class))
.describedAs("deleting an aggregate with a future version should raise an exception")
.hasRootCauseInstanceOf(OptimisticLockingFailureException.class);
//This should succeed
// This should succeed
template.delete(aggregate, AggregateWithImmutableVersion.class);
aggregate = new AggregateWithImmutableVersion(null, null);
aggregate = template.save(aggregate);
//This should succeed, as version will not be used.
// This should succeed, as version will not be used.
template.deleteById(aggregate.getId(), AggregateWithImmutableVersion.class);
}
@@ -1013,6 +1011,7 @@ public class JdbcAggregateTemplateIntegrationTests {
String name;
@ReadOnlyProperty String readOnly;
}
@Data
static abstract class VersionedAggregate {

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.jdbc.core.convert;
import static java.util.Collections.emptySet;
import static org.assertj.core.api.Assertions.assertThat;
import static java.util.Collections.*;
import static org.assertj.core.api.Assertions.*;
import java.util.Map;
import java.util.Set;
@@ -174,9 +174,9 @@ public class SqlGeneratorUnitTests {
public void findAllByPropertyWithMultipartIdentifier() {
// this would get called when ListParent is the element type of a Set
String sql = sqlGenerator.getFindAllByProperty(
Identifier.of("backref", "some-value", String.class).withPart("backref_key", "key-value", Object.class), null,
false);
Identifier parentIdentifier = Identifier.of("backref", "some-value", String.class) //
.withPart("backref_key", "key-value", Object.class);
String sql = sqlGenerator.getFindAllByProperty(parentIdentifier, null, false);
assertThat(sql).contains("SELECT", //
"dummy_entity.id1 AS id1", //
@@ -189,7 +189,8 @@ public class SqlGeneratorUnitTests {
"FROM dummy_entity ", //
"LEFT OUTER JOIN referenced_entity AS ref ON ref.dummy_entity = dummy_entity.id1", //
"LEFT OUTER JOIN second_level_referenced_entity AS ref_further ON ref_further.referenced_entity = ref.x_l1id", //
"dummy_entity.backref = :backref", "dummy_entity.backref_key = :backref_key");
"dummy_entity.backref = :backref", //
"dummy_entity.backref_key = :backref_key");
}
@Test // DATAJDBC-131, DATAJDBC-111

View File

@@ -53,6 +53,7 @@ import org.springframework.transaction.annotation.Transactional;
*
* @author Kazuki Shimizu
* @author Jens Schauder
* @author Tyler Van Gorder
*/
@ContextConfiguration
@ActiveProfiles("hsql")

View File

@@ -50,6 +50,7 @@ import org.springframework.data.relational.domain.Identifier;
*
* @author Jens Schauder
* @author Mark Paluch
* @author Tyler Van Gorder
*/
public class MyBatisDataAccessStrategyUnitTests {