Support safe-updates mode in MySQLMaxValueIncrementer
Prior to this commit, MySQLMaxValueIncrementer could not be used when the MySQL database was configured to use safe-updates mode. See https://dev.mysql.com/doc/refman/8.0/en/mysql-tips.html#safe-updates This commit introduces a `limit 1` clause to the generated update statement to allow MySQLMaxValueIncrementer to be compatible with MySQL safe-updates mode. Closes gh-26858
This commit is contained in:
parent
607d918340
commit
697108cc42
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -40,22 +40,27 @@ import org.springframework.jdbc.support.JdbcUtils;
|
|||
*
|
||||
* <p>Example:
|
||||
*
|
||||
* <pre class="code">create table tab (id int unsigned not null primary key, text varchar(100));
|
||||
* <pre class="code">
|
||||
* create table tab (id int unsigned not null primary key, text varchar(100));
|
||||
* create table tab_sequence (value int not null);
|
||||
* insert into tab_sequence values(0);</pre>
|
||||
*
|
||||
* If "cacheSize" is set, the intermediate values are served without querying the
|
||||
* <p>If {@code cacheSize} is set, the intermediate values are served without querying the
|
||||
* database. If the server or your application is stopped or crashes or a transaction
|
||||
* is rolled back, the unused values will never be served. The maximum hole size in
|
||||
* numbering is consequently the value of cacheSize.
|
||||
* numbering is consequently the value of {@code cacheSize}.
|
||||
*
|
||||
* <p>It is possible to avoid acquiring a new connection for the incrementer by setting the
|
||||
* "useNewConnection" property to false. In this case you <i>MUST</i> use a non-transactional
|
||||
* storage engine like MYISAM when defining the incrementer table.
|
||||
*
|
||||
* <p>As of Spring Framework 5.3.7, {@code MySQLMaxValueIncrementer} is compatible with
|
||||
* <a href="https://dev.mysql.com/doc/refman/8.0/en/mysql-tips.html#safe-updates">MySQL safe updates mode</a>.
|
||||
*
|
||||
* @author Jean-Pierre Pawlak
|
||||
* @author Thomas Risberg
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class MySQLMaxValueIncrementer extends AbstractColumnMaxValueIncrementer {
|
||||
|
||||
|
|
@ -141,7 +146,7 @@ public class MySQLMaxValueIncrementer extends AbstractColumnMaxValueIncrementer
|
|||
String columnName = getColumnName();
|
||||
try {
|
||||
stmt.executeUpdate("update " + getIncrementerName() + " set " + columnName +
|
||||
" = last_insert_id(" + columnName + " + " + getCacheSize() + ")");
|
||||
" = last_insert_id(" + columnName + " + " + getCacheSize() + ") limit 1");
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
throw new DataAccessResourceFailureException("Could not increment " + columnName + " for " +
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
|
|
@ -25,6 +25,7 @@ import javax.sql.DataSource;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer;
|
||||
import org.springframework.jdbc.support.incrementer.HanaSequenceMaxValueIncrementer;
|
||||
import org.springframework.jdbc.support.incrementer.HsqlMaxValueIncrementer;
|
||||
import org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer;
|
||||
|
|
@ -38,10 +39,13 @@ import static org.mockito.Mockito.times;
|
|||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DataFieldMaxValueIncrementer} implementations.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 27.02.2004
|
||||
*/
|
||||
public class DataFieldMaxValueIncrementerTests {
|
||||
class DataFieldMaxValueIncrementerTests {
|
||||
|
||||
private final DataSource dataSource = mock(DataSource.class);
|
||||
|
||||
|
|
@ -53,7 +57,7 @@ public class DataFieldMaxValueIncrementerTests {
|
|||
|
||||
|
||||
@Test
|
||||
public void testHanaSequenceMaxValueIncrementer() throws SQLException {
|
||||
void hanaSequenceMaxValueIncrementer() throws SQLException {
|
||||
given(dataSource.getConnection()).willReturn(connection);
|
||||
given(connection.createStatement()).willReturn(statement);
|
||||
given(statement.executeQuery("select myseq.nextval from dummy")).willReturn(resultSet);
|
||||
|
|
@ -75,7 +79,7 @@ public class DataFieldMaxValueIncrementerTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testHsqlMaxValueIncrementer() throws SQLException {
|
||||
void hsqlMaxValueIncrementer() throws SQLException {
|
||||
given(dataSource.getConnection()).willReturn(connection);
|
||||
given(connection.createStatement()).willReturn(statement);
|
||||
given(statement.executeQuery("select max(identity()) from myseq")).willReturn(resultSet);
|
||||
|
|
@ -105,7 +109,7 @@ public class DataFieldMaxValueIncrementerTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testHsqlMaxValueIncrementerWithDeleteSpecificValues() throws SQLException {
|
||||
void hsqlMaxValueIncrementerWithDeleteSpecificValues() throws SQLException {
|
||||
given(dataSource.getConnection()).willReturn(connection);
|
||||
given(connection.createStatement()).willReturn(statement);
|
||||
given(statement.executeQuery("select max(identity()) from myseq")).willReturn(resultSet);
|
||||
|
|
@ -136,7 +140,7 @@ public class DataFieldMaxValueIncrementerTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMySQLMaxValueIncrementer() throws SQLException {
|
||||
void mySQLMaxValueIncrementer() throws SQLException {
|
||||
given(dataSource.getConnection()).willReturn(connection);
|
||||
given(connection.createStatement()).willReturn(statement);
|
||||
given(statement.executeQuery("select last_insert_id()")).willReturn(resultSet);
|
||||
|
|
@ -156,14 +160,14 @@ public class DataFieldMaxValueIncrementerTests {
|
|||
assertThat(incrementer.nextStringValue()).isEqualTo("3");
|
||||
assertThat(incrementer.nextLongValue()).isEqualTo(4);
|
||||
|
||||
verify(statement, times(2)).executeUpdate("update myseq set seq = last_insert_id(seq + 2)");
|
||||
verify(statement, times(2)).executeUpdate("update myseq set seq = last_insert_id(seq + 2) limit 1");
|
||||
verify(resultSet, times(2)).close();
|
||||
verify(statement, times(2)).close();
|
||||
verify(connection, times(2)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOracleSequenceMaxValueIncrementer() throws SQLException {
|
||||
void oracleSequenceMaxValueIncrementer() throws SQLException {
|
||||
given(dataSource.getConnection()).willReturn(connection);
|
||||
given(connection.createStatement()).willReturn(statement);
|
||||
given(statement.executeQuery("select myseq.nextval from dual")).willReturn(resultSet);
|
||||
|
|
@ -185,7 +189,7 @@ public class DataFieldMaxValueIncrementerTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testPostgresSequenceMaxValueIncrementer() throws SQLException {
|
||||
void postgresSequenceMaxValueIncrementer() throws SQLException {
|
||||
given(dataSource.getConnection()).willReturn(connection);
|
||||
given(connection.createStatement()).willReturn(statement);
|
||||
given(statement.executeQuery("select nextval('myseq')")).willReturn(resultSet);
|
||||
|
|
|
|||
Loading…
Reference in New Issue