diff --git a/samples/java/spring-data-jpa/pom.xml b/samples/java/spring-data-jpa/pom.xml index 55ee92ec22..070a74fb99 100644 --- a/samples/java/spring-data-jpa/pom.xml +++ b/samples/java/spring-data-jpa/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.9 + 4.0.1 com.google.cloud.spanner @@ -37,8 +37,8 @@ - org.liquibase - liquibase-core + org.springframework.boot + spring-boot-starter-liquibase @@ -55,18 +55,18 @@ com.google.cloud google-cloud-spanner-pgadapter - 0.52.1 + 0.52.2-SNAPSHOT com.google.cloud google-cloud-spanner-hibernate-tools - 3.9.7 + 4.1.1 io.hypersistence - hypersistence-utils-hibernate-63 + hypersistence-utils-hibernate-71 3.14.1 diff --git a/samples/java/spring-data-jpa/src/main/java/com/google/cloud/spanner/pgadapter/sample/model/TicketSale.java b/samples/java/spring-data-jpa/src/main/java/com/google/cloud/spanner/pgadapter/sample/model/TicketSale.java index 435d640f6b..cb503abc82 100644 --- a/samples/java/spring-data-jpa/src/main/java/com/google/cloud/spanner/pgadapter/sample/model/TicketSale.java +++ b/samples/java/spring-data-jpa/src/main/java/com/google/cloud/spanner/pgadapter/sample/model/TicketSale.java @@ -14,22 +14,17 @@ package com.google.cloud.spanner.pgadapter.sample.model; -import com.google.cloud.spanner.hibernate.PooledBitReversedSequenceStyleGenerator; +import com.google.cloud.spanner.hibernate.annotations.PooledBitReversedSequenceGenerator; import io.hypersistence.utils.hibernate.type.array.ListArrayType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import java.math.BigDecimal; import java.util.List; -import org.hibernate.annotations.GenericGenerator; -import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Type; -import org.hibernate.id.enhanced.SequenceStyleGenerator; /** * This entity uses a bit-reversed sequence to generate a primary key. The strategy it uses is @@ -57,30 +52,18 @@ public class TicketSale extends AbstractBaseEntity { // options that Hibernate has to batch and optimize insert statements. When using a sequence, // Hibernate can pre-fetch a batch of primary key values and include these in the insert // statement. This again allows Hibernate to send those insert statements as one batch to the - // database and reduce the overall number of roundtrips. - @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ticketSaleId") - @GenericGenerator( - // This is the name of the generator, not the name of the sequence. This name must correspond - // with the name given in the @GeneratedValue above. - name = "ticketSaleId", - // Use this custom strategy to ensure the use of a bit-reversed sequence that is compatible - // with batching multiple inserts. See also - // https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#batch. - type = PooledBitReversedSequenceStyleGenerator.class, - parameters = { - // Use a separate sequence name for each entity. - // See resources/db.changelog-v1.1.sql file for the sequence definition in the database. - @Parameter(name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "ticket_sale_seq"), - // The increment_size is not actually set on the sequence that is created, but is used to - // generate a SELECT query that fetches this number of identifiers at once. - @Parameter(name = SequenceStyleGenerator.INCREMENT_PARAM, value = "200"), - @Parameter(name = SequenceStyleGenerator.INITIAL_PARAM, value = "50000"), - // Add any range that should be excluded by the generator if your table already - // contains existing values that have been generated by other generators. - @Parameter( - name = PooledBitReversedSequenceStyleGenerator.EXCLUDE_RANGE_PARAM, - value = "[1,1000]"), - }) + // database and reduce the overall number of round-trips. + @PooledBitReversedSequenceGenerator( + // Use a separate sequence name for each entity. + sequenceName = "ticket_sale_seq", + // The initial_value is used a starting counter used by spanner for producing bit-reversed ids + startWithCounter = 50000, + // The increment_size is not set on the sequence that is created on the spanner instance + // but is used to generate a SELECT query that fetches this number of identifiers at once. + poolSize = 200, + // Add any range that should be excluded by the generator if your table already + // contains existing values that have been generated by other generators. + excludeRange = "[1,1000]") public Long id; @ManyToOne(optional = false, fetch = FetchType.LAZY) @@ -92,13 +75,13 @@ public class TicketSale extends AbstractBaseEntity { /** * This column is mapped to a text[] column in the database. The {@link ListArrayType} is defined - * in the hypersistence-utils-hibernate-63 library. Add the following to your pom.xml to use it: + * in the hypersistence-utils-hibernate-71 library. Add the following to your pom.xml to use it: * *
{@code
    * 
    *   io.hypersistence
-   *   hypersistence-utils-hibernate-63
-   *   3.7.2
+   *   hypersistence-utils-hibernate-71
+   *   3.14.1
    * 
    * }
*/ diff --git a/samples/java/spring-data-jpa/src/main/resources/application.properties b/samples/java/spring-data-jpa/src/main/resources/application.properties index 1e8a964735..58a82512e4 100644 --- a/samples/java/spring-data-jpa/src/main/resources/application.properties +++ b/samples/java/spring-data-jpa/src/main/resources/application.properties @@ -4,7 +4,7 @@ spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect # This sample by default runs on the Spanner emulator. Disable this to run on a real Spanner # instance. -spanner.use_emulator=true +spanner.use_emulator=false # Defining these properties here makes it a bit easier to build the connection string. # Change these to match your Cloud Spanner PostgreSQL-dialect database. diff --git a/src/main/java/com/google/cloud/spanner/pgadapter/statements/SimpleParser.java b/src/main/java/com/google/cloud/spanner/pgadapter/statements/SimpleParser.java index 9ba69fde0b..8241fe07d2 100644 --- a/src/main/java/com/google/cloud/spanner/pgadapter/statements/SimpleParser.java +++ b/src/main/java/com/google/cloud/spanner/pgadapter/statements/SimpleParser.java @@ -252,6 +252,13 @@ static Statement replaceForUpdate( return statement; } int startPos = parser.pos; + if (!replaceWithHint + && parser.eatKeyword("for", "no", "key", "update") + && !parser.hasMoreTokens()) { + // Replace FOR NO KEY UPDATE with FOR UPDATE. + return statement.withReplacedSql(statement.getSql().substring(0, startPos) + " for update"); + } + parser.pos = startPos; if (parser.eatKeyword("for") && parser.eatKeyword("update")) { if (!replaceWithHint) { startPos = parser.pos; @@ -278,12 +285,12 @@ static Statement replaceForUpdate( // This is a simple 'for update' clause. Replace it with a 'LOCK_SCANNED_RANGES=exclusive' // hint and/or remove the 'of table' clause. if (replaceWithHint) { - return Statement.of( + return statement.withReplacedSql( "/*@ LOCK_SCANNED_RANGES=exclusive */" + statement.getSql().substring(0, startPos) + statement.getSql().substring(endPos)); } else { - return Statement.of( + return statement.withReplacedSql( statement.getSql().substring(0, startPos) + statement.getSql().substring(endPos)); } }