DATAJDBC-493 - Polishing.
Using `execute` instead of `query` since we are not interested in the results. Refactoring of the concurrency tests. Make the concurrency tests run with all databases. Added support for DB2. Moved AnsiDialect to the main sources so it can be referenced in other Dialects. Original pull request: #196.
This commit is contained in:
@@ -23,9 +23,8 @@ import org.junit.Test;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.core.mapping.PersistentPropertyPathTestUtils;
|
||||
import org.springframework.data.jdbc.testing.AnsiDialect;
|
||||
import org.springframework.data.relational.core.dialect.AnsiDialect;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
import org.springframework.data.relational.core.dialect.HsqlDbDialect;
|
||||
import org.springframework.data.relational.core.mapping.NamingStrategy;
|
||||
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
|
||||
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.util.Set;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
import org.springframework.data.annotation.Version;
|
||||
@@ -36,7 +35,7 @@ import org.springframework.data.jdbc.core.PropertyPathTestingUtils;
|
||||
import org.springframework.data.jdbc.core.mapping.AggregateReference;
|
||||
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
|
||||
import org.springframework.data.jdbc.core.mapping.PersistentPropertyPathTestUtils;
|
||||
import org.springframework.data.jdbc.testing.AnsiDialect;
|
||||
import org.springframework.data.relational.core.dialect.AnsiDialect;
|
||||
import org.springframework.data.mapping.PersistentPropertyPath;
|
||||
import org.springframework.data.relational.core.dialect.Dialect;
|
||||
import org.springframework.data.relational.core.mapping.Column;
|
||||
@@ -95,19 +94,18 @@ public class SqlGeneratorUnitTests {
|
||||
|
||||
String sql = sqlGenerator.getFindOne();
|
||||
|
||||
SoftAssertions softAssertions = new SoftAssertions();
|
||||
softAssertions.assertThat(sql) //
|
||||
.startsWith("SELECT") //
|
||||
.contains("dummy_entity.id1 AS id1,") //
|
||||
.contains("dummy_entity.x_name AS x_name,") //
|
||||
.contains("dummy_entity.x_other AS x_other,") //
|
||||
.contains("ref.x_l1id AS ref_x_l1id") //
|
||||
.contains("ref.x_content AS ref_x_content").contains(" FROM dummy_entity") //
|
||||
.contains("ON ref.dummy_entity = dummy_entity.id1") //
|
||||
.contains("WHERE dummy_entity.id1 = :id") //
|
||||
// 1-N relationships do not get loaded via join
|
||||
.doesNotContain("Element AS elements");
|
||||
softAssertions.assertAll();
|
||||
SoftAssertions.assertSoftly(softly -> softly //
|
||||
.assertThat(sql) //
|
||||
.startsWith("SELECT") //
|
||||
.contains("dummy_entity.id1 AS id1,") //
|
||||
.contains("dummy_entity.x_name AS x_name,") //
|
||||
.contains("dummy_entity.x_other AS x_other,") //
|
||||
.contains("ref.x_l1id AS ref_x_l1id") //
|
||||
.contains("ref.x_content AS ref_x_content").contains(" FROM dummy_entity") //
|
||||
.contains("ON ref.dummy_entity = dummy_entity.id1") //
|
||||
.contains("WHERE dummy_entity.id1 = :id") //
|
||||
// 1-N relationships do not get loaded via join
|
||||
.doesNotContain("Element AS elements"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-493
|
||||
@@ -115,14 +113,13 @@ public class SqlGeneratorUnitTests {
|
||||
|
||||
String sql = sqlGenerator.getAcquireLockById(LockMode.PESSIMISTIC_WRITE);
|
||||
|
||||
SoftAssertions softAssertions = new SoftAssertions();
|
||||
softAssertions.assertThat(sql) //
|
||||
.startsWith("SELECT") //
|
||||
.contains("dummy_entity.id1") //
|
||||
.contains("WHERE dummy_entity.id1 = :id") //
|
||||
.contains("FOR UPDATE") //
|
||||
.doesNotContain("Element AS elements");
|
||||
softAssertions.assertAll();
|
||||
SoftAssertions.assertSoftly(softly -> softly //
|
||||
.assertThat(sql) //
|
||||
.startsWith("SELECT") //
|
||||
.contains("dummy_entity.id1") //
|
||||
.contains("WHERE dummy_entity.id1 = :id") //
|
||||
.contains("FOR UPDATE") //
|
||||
.doesNotContain("Element AS elements"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-493
|
||||
@@ -130,13 +127,12 @@ public class SqlGeneratorUnitTests {
|
||||
|
||||
String sql = sqlGenerator.getAcquireLockAll(LockMode.PESSIMISTIC_WRITE);
|
||||
|
||||
SoftAssertions softAssertions = new SoftAssertions();
|
||||
softAssertions.assertThat(sql) //
|
||||
.startsWith("SELECT") //
|
||||
.contains("dummy_entity.id1") //
|
||||
.contains("FOR UPDATE") //
|
||||
.doesNotContain("Element AS elements");
|
||||
softAssertions.assertAll();
|
||||
SoftAssertions.assertSoftly(softly -> softly //
|
||||
.assertThat(sql) //
|
||||
.startsWith("SELECT") //
|
||||
.contains("dummy_entity.id1") //
|
||||
.contains("FOR UPDATE") //
|
||||
.doesNotContain("Element AS elements"));
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-112
|
||||
|
||||
@@ -15,10 +15,21 @@
|
||||
*/
|
||||
package org.springframework.data.jdbc.repository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.With;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -29,34 +40,20 @@ import org.springframework.context.annotation.Import;
|
||||
import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.jdbc.repository.support.JdbcRepositoryFactory;
|
||||
import org.springframework.data.jdbc.testing.DatabaseProfileValueSource;
|
||||
import org.springframework.data.jdbc.testing.TestConfiguration;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.test.annotation.IfProfileValue;
|
||||
import org.springframework.test.annotation.ProfileValueSourceConfiguration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.rules.SpringClassRule;
|
||||
import org.springframework.test.context.junit4.rules.SpringMethodRule;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/** Tests that highly concurrent update operations of an entity don't cause deadlocks.
|
||||
/**
|
||||
* Tests that highly concurrent update operations of an entity don't cause deadlocks.
|
||||
*
|
||||
* @author Myeonghyeon Lee
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@ProfileValueSourceConfiguration(DatabaseProfileValueSource.class)
|
||||
@IfProfileValue(name = "current.database.is.not.mysql", value = "false")
|
||||
public class JdbcRepositoryConcurrencyIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@@ -83,38 +80,37 @@ public class JdbcRepositoryConcurrencyIntegrationTests {
|
||||
@Autowired DummyEntityRepository repository;
|
||||
@Autowired PlatformTransactionManager transactionManager;
|
||||
|
||||
@Test // DATAJDBC-488
|
||||
public void updateConcurrencyWithEmptyReferences() throws Exception {
|
||||
List<DummyEntity> concurrencyEntities;
|
||||
DummyEntity entity;
|
||||
|
||||
DummyEntity entity = createDummyEntity();
|
||||
entity = repository.save(entity);
|
||||
TransactionTemplate transactionTemplate;
|
||||
List<Exception> exceptions;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
entity = repository.save(createDummyEntity());
|
||||
|
||||
assertThat(entity.getId()).isNotNull();
|
||||
|
||||
List<DummyEntity> concurrencyEntities = createEntityStates(entity);
|
||||
concurrencyEntities = createEntityStates(entity);
|
||||
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(this.transactionManager);
|
||||
transactionTemplate = new TransactionTemplate(this.transactionManager);
|
||||
|
||||
List<Exception> exceptions = new CopyOnWriteArrayList<>();
|
||||
CountDownLatch startLatch = new CountDownLatch(concurrencyEntities.size()); // latch for all threads to wait on.
|
||||
CountDownLatch doneLatch = new CountDownLatch(concurrencyEntities.size()); // latch for main thread to wait on until all threads are done.
|
||||
exceptions = new CopyOnWriteArrayList<>();
|
||||
}
|
||||
|
||||
concurrencyEntities.stream() //
|
||||
.map(e -> new Thread(() -> {
|
||||
@Test // DATAJDBC-488
|
||||
public void updateConcurrencyWithEmptyReferences() throws Exception {
|
||||
|
||||
try {
|
||||
// latch for all threads to wait on.
|
||||
CountDownLatch startLatch = new CountDownLatch(concurrencyEntities.size());
|
||||
// latch for main thread to wait on until all threads are done.
|
||||
CountDownLatch doneLatch = new CountDownLatch(concurrencyEntities.size());
|
||||
|
||||
startLatch.countDown();
|
||||
startLatch.await();
|
||||
UnaryOperator<DummyEntity> action = e -> repository.save(e);
|
||||
|
||||
transactionTemplate.execute(status -> repository.save(e));
|
||||
} catch (Exception ex) {
|
||||
exceptions.add(ex);
|
||||
} finally {
|
||||
doneLatch.countDown();
|
||||
}
|
||||
})) //
|
||||
.forEach(Thread::start);
|
||||
concurrencyEntities.forEach(e -> executeInParallel(startLatch, doneLatch, action, e));
|
||||
|
||||
doneLatch.await();
|
||||
|
||||
@@ -124,62 +120,31 @@ public class JdbcRepositoryConcurrencyIntegrationTests {
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-493
|
||||
public void updateConcurrencyWithDelete() throws Exception {
|
||||
public void concurrentUpdateAndDelete() throws Exception {
|
||||
|
||||
DummyEntity entity = createDummyEntity();
|
||||
entity = repository.save(entity);
|
||||
|
||||
Long targetId = entity.getId();
|
||||
assertThat(targetId).isNotNull();
|
||||
|
||||
List<DummyEntity> concurrencyEntities = createEntityStates(entity);
|
||||
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(this.transactionManager);
|
||||
|
||||
List<Exception> exceptions = new CopyOnWriteArrayList<>();
|
||||
CountDownLatch startLatch = new CountDownLatch(concurrencyEntities.size() + 1); // latch for all threads to wait on.
|
||||
CountDownLatch doneLatch = new CountDownLatch(concurrencyEntities.size() + 1); // latch for main thread to wait on until all threads are done.
|
||||
|
||||
// update
|
||||
concurrencyEntities.stream() //
|
||||
.map(e -> new Thread(() -> {
|
||||
|
||||
try {
|
||||
|
||||
startLatch.countDown();
|
||||
startLatch.await();
|
||||
|
||||
transactionTemplate.execute(status -> repository.save(e));
|
||||
} catch (Exception ex) {
|
||||
// When the delete execution is complete, the Update execution throws an IncorrectUpdateSemanticsDataAccessException.
|
||||
if (ex.getCause() instanceof IncorrectUpdateSemanticsDataAccessException) {
|
||||
return;
|
||||
}
|
||||
|
||||
exceptions.add(ex);
|
||||
} finally {
|
||||
doneLatch.countDown();
|
||||
}
|
||||
})) //
|
||||
.forEach(Thread::start);
|
||||
|
||||
// delete
|
||||
new Thread(() -> {
|
||||
CountDownLatch doneLatch = new CountDownLatch(concurrencyEntities.size() + 1); // latch for main thread to wait on
|
||||
// until all threads are done.
|
||||
UnaryOperator<DummyEntity> updateAction = e -> {
|
||||
try {
|
||||
|
||||
startLatch.countDown();
|
||||
startLatch.await();
|
||||
|
||||
transactionTemplate.execute(status -> {
|
||||
repository.deleteById(targetId);
|
||||
return null;
|
||||
});
|
||||
return repository.save(e);
|
||||
} catch (Exception ex) {
|
||||
exceptions.add(ex);
|
||||
} finally {
|
||||
doneLatch.countDown();
|
||||
// When the delete execution is complete, the Update execution throws an
|
||||
// IncorrectUpdateSemanticsDataAccessException.
|
||||
if (ex.getCause() instanceof IncorrectUpdateSemanticsDataAccessException) {
|
||||
return null;
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}).start();
|
||||
};
|
||||
|
||||
UnaryOperator<DummyEntity> deleteAction = e -> {
|
||||
repository.deleteById(entity.id);
|
||||
return null;
|
||||
};
|
||||
|
||||
concurrencyEntities.forEach(e -> executeInParallel(startLatch, doneLatch, updateAction, e));
|
||||
executeInParallel(startLatch, doneLatch, deleteAction, entity);
|
||||
|
||||
doneLatch.await();
|
||||
|
||||
@@ -188,42 +153,41 @@ public class JdbcRepositoryConcurrencyIntegrationTests {
|
||||
}
|
||||
|
||||
@Test // DATAJDBC-493
|
||||
public void updateConcurrencyWithDeleteAll() throws Exception {
|
||||
public void concurrentUpdateAndDeleteAll() throws Exception {
|
||||
|
||||
DummyEntity entity = createDummyEntity();
|
||||
entity = repository.save(entity);
|
||||
|
||||
List<DummyEntity> concurrencyEntities = createEntityStates(entity);
|
||||
|
||||
TransactionTemplate transactionTemplate = new TransactionTemplate(this.transactionManager);
|
||||
|
||||
List<Exception> exceptions = new CopyOnWriteArrayList<>();
|
||||
CountDownLatch startLatch = new CountDownLatch(concurrencyEntities.size() + 1); // latch for all threads to wait on.
|
||||
CountDownLatch doneLatch = new CountDownLatch(concurrencyEntities.size() + 1); // latch for main thread to wait on until all threads are done.
|
||||
CountDownLatch doneLatch = new CountDownLatch(concurrencyEntities.size() + 1); // latch for main thread to wait on
|
||||
// until all threads are done.
|
||||
|
||||
// update
|
||||
concurrencyEntities.stream() //
|
||||
.map(e -> new Thread(() -> {
|
||||
|
||||
try {
|
||||
|
||||
startLatch.countDown();
|
||||
startLatch.await();
|
||||
|
||||
transactionTemplate.execute(status -> repository.save(e));
|
||||
} catch (Exception ex) {
|
||||
// When the delete execution is complete, the Update execution throws an IncorrectUpdateSemanticsDataAccessException.
|
||||
if (ex.getCause() instanceof IncorrectUpdateSemanticsDataAccessException) {
|
||||
return;
|
||||
}
|
||||
|
||||
exceptions.add(ex);
|
||||
} finally {
|
||||
doneLatch.countDown();
|
||||
UnaryOperator<DummyEntity> updateAction = e -> {
|
||||
try {
|
||||
return repository.save(e);
|
||||
} catch (Exception ex) {
|
||||
// When the delete execution is complete, the Update execution throws an
|
||||
// IncorrectUpdateSemanticsDataAccessException.
|
||||
if (ex.getCause() instanceof IncorrectUpdateSemanticsDataAccessException) {
|
||||
return null;
|
||||
}
|
||||
})) //
|
||||
.forEach(Thread::start);
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
|
||||
UnaryOperator<DummyEntity> deleteAction = e -> {
|
||||
repository.deleteAll();
|
||||
return null;
|
||||
};
|
||||
|
||||
concurrencyEntities.forEach(e -> executeInParallel(startLatch, doneLatch, updateAction, e));
|
||||
executeInParallel(startLatch, doneLatch, deleteAction, entity);
|
||||
|
||||
doneLatch.await();
|
||||
|
||||
assertThat(exceptions).isEmpty();
|
||||
assertThat(repository.count()).isEqualTo(0);
|
||||
}
|
||||
|
||||
private void executeInParallel(CountDownLatch startLatch, CountDownLatch doneLatch,
|
||||
UnaryOperator<DummyEntity> deleteAction, DummyEntity entity) {
|
||||
// delete
|
||||
new Thread(() -> {
|
||||
try {
|
||||
@@ -231,21 +195,13 @@ public class JdbcRepositoryConcurrencyIntegrationTests {
|
||||
startLatch.countDown();
|
||||
startLatch.await();
|
||||
|
||||
transactionTemplate.execute(status -> {
|
||||
repository.deleteAll();
|
||||
return null;
|
||||
});
|
||||
transactionTemplate.execute(status -> deleteAction.apply(entity));
|
||||
} catch (Exception ex) {
|
||||
exceptions.add(ex);
|
||||
} finally {
|
||||
doneLatch.countDown();
|
||||
}
|
||||
}).start();
|
||||
|
||||
doneLatch.await();
|
||||
|
||||
assertThat(exceptions).isEmpty();
|
||||
assertThat(repository.count()).isEqualTo(0);
|
||||
}
|
||||
|
||||
private List<DummyEntity> createEntityStates(DummyEntity entity) {
|
||||
@@ -254,7 +210,7 @@ public class JdbcRepositoryConcurrencyIntegrationTests {
|
||||
Element element1 = new Element(null, 1L);
|
||||
Element element2 = new Element(null, 2L);
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
for (int i = 0; i < 50; i++) {
|
||||
|
||||
List<Element> newContent = Arrays.asList(element1.withContent(element1.content + i + 2),
|
||||
element2.withContent(element2.content + i + 2));
|
||||
|
||||
@@ -64,7 +64,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
* @author Jens Schauder
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@Transactional
|
||||
public class JdbcRepositoryIntegrationTests {
|
||||
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jdbc.testing;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.relational.core.dialect.AbstractDialect;
|
||||
import org.springframework.data.relational.core.dialect.ArrayColumns;
|
||||
import org.springframework.data.relational.core.dialect.LimitClause;
|
||||
import org.springframework.data.relational.core.dialect.LockClause;
|
||||
import org.springframework.data.relational.core.sql.IdentifierProcessing;
|
||||
import org.springframework.data.relational.core.sql.LockOptions;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* An SQL dialect for the ANSI SQL standard.
|
||||
*
|
||||
* @author Milan Milanov
|
||||
* @author Myeonghyeon Lee
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AnsiDialect extends AbstractDialect {
|
||||
|
||||
/**
|
||||
* Singleton instance.
|
||||
*/
|
||||
public static final AnsiDialect INSTANCE = new AnsiDialect();
|
||||
|
||||
protected AnsiDialect() {}
|
||||
|
||||
private static final LimitClause LIMIT_CLAUSE = new LimitClause() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.LimitClause#getLimit(long)
|
||||
*/
|
||||
@Override
|
||||
public String getLimit(long limit) {
|
||||
return String.format("FETCH FIRST %d ROWS ONLY", limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.LimitClause#getOffset(long)
|
||||
*/
|
||||
@Override
|
||||
public String getOffset(long offset) {
|
||||
return String.format("OFFSET %d ROWS", offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.LimitClause#getClause(long, long)
|
||||
*/
|
||||
@Override
|
||||
public String getLimitOffset(long limit, long offset) {
|
||||
return String.format("OFFSET %d ROWS FETCH FIRST %d ROWS ONLY", offset, limit);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.LimitClause#getClausePosition()
|
||||
*/
|
||||
@Override
|
||||
public Position getClausePosition() {
|
||||
return Position.AFTER_ORDER_BY;
|
||||
}
|
||||
};
|
||||
|
||||
private static final LockClause LOCK_CLAUSE = new LockClause() {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.LockClause#getLock(LockOptions)
|
||||
*/
|
||||
@Override
|
||||
public String getLock(LockOptions lockOptions) {
|
||||
return "FOR UPDATE";
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.LimitClause#getClausePosition()
|
||||
*/
|
||||
@Override
|
||||
public Position getClausePosition() {
|
||||
return Position.AFTER_ORDER_BY;
|
||||
}
|
||||
};
|
||||
|
||||
private final AnsiArrayColumns ARRAY_COLUMNS = new AnsiArrayColumns();
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.Dialect#limit()
|
||||
*/
|
||||
@Override
|
||||
public LimitClause limit() {
|
||||
return LIMIT_CLAUSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.Dialect#lock()
|
||||
*/
|
||||
@Override
|
||||
public LockClause lock() {
|
||||
return LOCK_CLAUSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.Dialect#getArraySupport()
|
||||
*/
|
||||
@Override
|
||||
public ArrayColumns getArraySupport() {
|
||||
return ARRAY_COLUMNS;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
static class AnsiArrayColumns implements ArrayColumns {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#isSupported()
|
||||
*/
|
||||
@Override
|
||||
public boolean isSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.relational.core.dialect.ArrayColumns#getArrayType(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getArrayType(Class<?> userType) {
|
||||
|
||||
Assert.notNull(userType, "Array component type must not be null");
|
||||
|
||||
return ClassUtils.resolvePrimitiveIfNecessary(userType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IdentifierProcessing getIdentifierProcessing() {
|
||||
return IdentifierProcessing.ANSI;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE dummy_entity ( id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element (id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, content BIGINT, Dummy_Entity_key BIGINT,dummy_entity BIGINT);
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE dummy_entity ( id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element (id BIGINT GENERATED BY DEFAULT AS IDENTITY ( START WITH 1 ) PRIMARY KEY, content BIGINT, Dummy_Entity_key BIGINT,dummy_entity BIGINT);
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE dummy_entity ( id BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element (id BIGINT AUTO_INCREMENT PRIMARY KEY, content BIGINT, Dummy_Entity_key BIGINT,dummy_entity BIGINT);
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE dummy_entity ( id BIGINT AUTO_INCREMENT PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element (id BIGINT AUTO_INCREMENT PRIMARY KEY, content BIGINT, Dummy_Entity_key BIGINT,dummy_entity BIGINT);
|
||||
@@ -0,0 +1,4 @@
|
||||
DROP TABLE dummy_entity;
|
||||
DROP TABLE element;
|
||||
CREATE TABLE dummy_entity ( id SERIAL PRIMARY KEY, NAME VARCHAR(100));
|
||||
CREATE TABLE element (id SERIAL PRIMARY KEY, content BIGINT, Dummy_Entity_key BIGINT,dummy_entity BIGINT);
|
||||
Reference in New Issue
Block a user