From d86e3b90cf6bc8d34dc7b21afd01174ed73da6c1 Mon Sep 17 00:00:00 2001 From: Michael Reiche <48999328+mikereiche@users.noreply.github.com> Date: Wed, 5 Oct 2022 09:29:46 -1000 Subject: [PATCH] Update spring-data-testapp for transactions. (#1577) Closed #1576. --- .../java/com/example/demo/AirlineGates.java | 72 +++++++++++++ .../example/demo/AirlineGatesRepository.java | 30 ++++++ .../com/example/demo/AirlineGatesService.java | 91 ++++++++++++++++ .../main/java/com/example/demo/Airport.java | 102 ------------------ .../com/example/demo/AirportRepository.java | 96 ----------------- .../java/com/example/demo/AirportService.java | 56 ---------- .../main/java/com/example/demo/CmdRunner.java | 102 ++++++++++-------- .../main/java/com/example/demo/Config.java | 7 +- 8 files changed, 258 insertions(+), 298 deletions(-) create mode 100644 spring-data-testapp/src/main/java/com/example/demo/AirlineGates.java create mode 100644 spring-data-testapp/src/main/java/com/example/demo/AirlineGatesRepository.java create mode 100644 spring-data-testapp/src/main/java/com/example/demo/AirlineGatesService.java delete mode 100644 spring-data-testapp/src/main/java/com/example/demo/Airport.java delete mode 100644 spring-data-testapp/src/main/java/com/example/demo/AirportRepository.java delete mode 100644 spring-data-testapp/src/main/java/com/example/demo/AirportService.java diff --git a/spring-data-testapp/src/main/java/com/example/demo/AirlineGates.java b/spring-data-testapp/src/main/java/com/example/demo/AirlineGates.java new file mode 100644 index 00000000..c2a16697 --- /dev/null +++ b/spring-data-testapp/src/main/java/com/example/demo/AirlineGates.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012-2022 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 com.example.demo; + +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.PersistenceConstructor; +import org.springframework.data.annotation.Version; +import org.springframework.data.couchbase.core.index.QueryIndexed; +import org.springframework.data.couchbase.core.mapping.Document; + +@Document +/** + * @author Michael Reiche + */ +public class AirlineGates { + @Id String id; + @Version Long version; + + @QueryIndexed String name; + String iata; + Long gates; + + @PersistenceConstructor + public AirlineGates(String id, String name, String iata, Long gates) { + this.id = id; + this.name = name; + this.iata = iata; + this.gates = gates; + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getIata() { + return iata; + } + + public Long getGates() { + return gates; + } + + public String toString(){ + StringBuffer sb=new StringBuffer(); + sb.append("{"); + sb.append("\"id\":"+id); + sb.append(", \"name\":"+name); + sb.append(", \"iata\":"+iata); + sb.append(", \"gates\":"+gates); + sb.append("}"); + + return sb.toString(); + } + +} diff --git a/spring-data-testapp/src/main/java/com/example/demo/AirlineGatesRepository.java b/spring-data-testapp/src/main/java/com/example/demo/AirlineGatesRepository.java new file mode 100644 index 00000000..49b974ed --- /dev/null +++ b/spring-data-testapp/src/main/java/com/example/demo/AirlineGatesRepository.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2022 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 com.example.demo; + +import org.springframework.data.couchbase.repository.CouchbaseRepository; +import org.springframework.data.couchbase.repository.DynamicProxyable; +import org.springframework.stereotype.Repository; + +/** + * @author Michael Reiche + */ +@Repository +public interface AirlineGatesRepository + extends CouchbaseRepository, DynamicProxyable { + +} diff --git a/spring-data-testapp/src/main/java/com/example/demo/AirlineGatesService.java b/spring-data-testapp/src/main/java/com/example/demo/AirlineGatesService.java new file mode 100644 index 00000000..b6c8a16c --- /dev/null +++ b/spring-data-testapp/src/main/java/com/example/demo/AirlineGatesService.java @@ -0,0 +1,91 @@ +/* + * Copyright 2022 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 com.example.demo; + +import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.data.couchbase.core.ReactiveCouchbaseOperations; +import org.springframework.data.couchbase.core.ReactiveCouchbaseTemplate; +import org.springframework.data.couchbase.core.TransactionalSupport; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import reactor.core.publisher.Mono; + +/** + * @author Michael Reiche + */ +@Service +public class AirlineGatesService { + CouchbaseTemplate template; + ReactiveCouchbaseTemplate reactiveTemplate; + public AirlineGatesService(CouchbaseTemplate template) { + this.template = template; + this.reactiveTemplate = template.reactive(); + } + + + // The @Transactional annotation results in the method of the proxy for the service executing this in a transaction + @Transactional + public void transferGates(String fromId, String toId, int gatesToTransfer, RuntimeException exceptionToThrow) { + // May wish to include this check to confirm this is actually in a transaction. + TransactionalSupport.checkForTransactionInThreadLocalStorage().map((h) -> { + if (!h.isPresent()) + throw new RuntimeException("not in transaction!"); + return h; + }); + + AirlineGates fromAirlineGates = template.findById(AirlineGates.class).one(fromId); + AirlineGates toAirlineGates = template.findById(AirlineGates.class).one(toId); + toAirlineGates.gates += gatesToTransfer; + fromAirlineGates.gates -= gatesToTransfer; + template.save(fromAirlineGates); + if(exceptionToThrow != null){ + throw exceptionToThrow; + } + template.save(toAirlineGates); + } + // The @Transactional annotation results in the method of the proxy for the service executing this in a transaction + @Transactional + public Mono transferGatesReactive(String fromId, String toId, int gatesToTransfer, RuntimeException exceptionToThrow) { + return Mono.deferContextual(ctx -> { + // May wish to include this check to confirm this is actually in a transaction. + TransactionalSupport.checkForTransactionInThreadLocalStorage().map((h) -> { + if (!h.isPresent()) + throw new RuntimeException("not in transaction!"); + return h; + }); + + AirlineGates fromAirlineGates = template.findById(AirlineGates.class).one(fromId); + AirlineGates toAirlineGates = template.findById(AirlineGates.class).one(toId); + toAirlineGates.gates += gatesToTransfer; + fromAirlineGates.gates -= gatesToTransfer; + template.save(fromAirlineGates); + if(exceptionToThrow != null){ + throw exceptionToThrow; + } + return reactiveTemplate.save(toAirlineGates).then(); + }); + } + + // This does not have the @Transactional annotation therefore is not executed in a transaction + public AirlineGates save(AirlineGates airlineGates) { + return template.save(airlineGates); + } + + // This does not have the @Transactional annotation therefore is not executed in a transaction + public AirlineGates findById(String id) { + return template.findById(AirlineGates.class).one(id); + } +} diff --git a/spring-data-testapp/src/main/java/com/example/demo/Airport.java b/spring-data-testapp/src/main/java/com/example/demo/Airport.java deleted file mode 100644 index 15f217ad..00000000 --- a/spring-data-testapp/src/main/java/com/example/demo/Airport.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2022 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 com.example.demo; - -import org.springframework.data.annotation.CreatedBy; -import org.springframework.data.annotation.Id; -import org.springframework.data.annotation.PersistenceConstructor; -import org.springframework.data.annotation.TypeAlias; -import org.springframework.data.annotation.Version; -import org.springframework.data.couchbase.core.mapping.Document; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -/** - * Airport entity - * - * @author Michael Reiche - */ -@Document -@TypeAlias("airport") -public class Airport { - @Id String id; - String iata; - String icao; - LocalDateTime openDate; - Long gates; - String _class; - @Version Number version; - @CreatedBy private String createdBy; - - public Airport() {} - - //@PersistenceConstructor - public Airport(String id, String iata, String icao) { - this.id = id; - this.iata = iata; - this.icao = icao; - this.openDate = null; // LocalDateTime.now(); - this.gates = Long.valueOf(200); - } - - public String getId() { - return id; - } - - public String getIata() { - return iata; - } - - public String getIcao() { - return icao; - } - - public Long getGates() { - return gates; - } - - public String get_class() { - return _class; - } - - public LocalDateTime getOpenDate() { - return openDate; - } - - public Airport clearVersion() { - version = Long.valueOf(0); - return this; - } - - public String getCreatedBy() { - return createdBy; - } - - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("{ "); - sb.append(" id: " + id); - sb.append(" iata: " + iata); - sb.append(" icao: " + icao); - sb.append(" gates: " + gates); - sb.append(" open: "+openDate); - // sb.append(" date: "+openDate); - sb.append(" }"); - return sb.toString(); - } -} diff --git a/spring-data-testapp/src/main/java/com/example/demo/AirportRepository.java b/spring-data-testapp/src/main/java/com/example/demo/AirportRepository.java deleted file mode 100644 index 44d32165..00000000 --- a/spring-data-testapp/src/main/java/com/example/demo/AirportRepository.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2022 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 com.example.demo; - -import com.couchbase.client.java.query.QueryScanConsistency; -import org.springframework.data.couchbase.core.RemoveResult; -import org.springframework.data.couchbase.core.mapping.Document; -import org.springframework.data.couchbase.repository.CouchbaseRepository; -import org.springframework.data.couchbase.repository.Query; -import org.springframework.data.couchbase.repository.ScanConsistency; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; - -/** - * Airport repository for testing
- * - * @author Michael Reiche - */ -@Repository -@Document -public interface AirportRepository extends CouchbaseRepository { - - // override an annotate with REQUEST_PLUS - @Override - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - List findAll(); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - List findAllByIata(String iata); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - Airport findByIata(String iata); - - @ScanConsistency(query = QueryScanConsistency.NOT_BOUNDED) - Airport iata(String iata); - - @Query("#{#n1ql.selectEntity} where iata = $1") - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - List getAllByIata(String iata); - - @Query("#{#n1ql.delete} WHERE #{#n1ql.filter} and iata = $1 #{#n1ql.returning}") - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - List deleteByIata(String iata); - - @Query("SELECT __cas, * from `#{#n1ql.bucket}` where iata = $1") - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - List getAllByIataNoID(String iata); - - @Query("SELECT __id, * from `#{#n1ql.bucket}` where iata = $1") - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - List getAllByIataNoCAS(String iata); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - long countByIataIn(String... iata); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - long countByIcaoAndIataIn(String icao, String... iata); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - long countByIcaoOrIataIn(String icao, String... iata); - - @Override - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - long count(); - - @Query("#{#n1ql.selectEntity} WHERE #{#n1ql.filter} #{#projectIds != null ? 'AND iata IN $1' : ''} " - + " #{#planIds != null ? 'AND icao IN $2' : ''} #{#active != null ? 'AND false = $3' : ''} ") - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - Long countFancyExpression(@Param("projectIds") List projectIds, @Param("planIds") List planIds, - @Param("active") Boolean active); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - Page findAllByIataNot(String iata, Pageable pageable); - - @ScanConsistency(query = QueryScanConsistency.REQUEST_PLUS) - Optional findByIdAndIata(String id, String iata); - -} diff --git a/spring-data-testapp/src/main/java/com/example/demo/AirportService.java b/spring-data-testapp/src/main/java/com/example/demo/AirportService.java deleted file mode 100644 index 6c0d6118..00000000 --- a/spring-data-testapp/src/main/java/com/example/demo/AirportService.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2022 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 com.example.demo; - -import com.couchbase.client.java.transactions.TransactionResult; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.couchbase.core.CouchbaseTemplate; -import org.springframework.data.couchbase.core.TransactionalSupport; -import org.springframework.stereotype.Component; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.Assert; - -/** - * - * - * @author Michael Reiche - */ -@Service -@Transactional -public class AirportService { - - public AirportService(CouchbaseTemplate template){ - this.template = template; - } - - CouchbaseTemplate template; - public void transferGates(String fromId, String toId, int gatesToTransfer) { - TransactionalSupport.checkForTransactionInThreadLocalStorage() - .map( (h) -> { if ( ! h.isPresent() ) throw new RuntimeException("not in transaction!"); return h; } ); - - TransactionalSupport.checkForTransactionInThreadLocalStorage().map(stat -> { - Assert.isTrue(stat.isPresent(), "Not in transaction"); - return stat; - }); - Airport fromAirport = template.findById(Airport.class).one(fromId); - Airport toAirport = template.findById(Airport.class).one(toId); - toAirport.gates += gatesToTransfer; - fromAirport.gates -= gatesToTransfer; - template.save(fromAirport); - template.save(toAirport); - } -} diff --git a/spring-data-testapp/src/main/java/com/example/demo/CmdRunner.java b/spring-data-testapp/src/main/java/com/example/demo/CmdRunner.java index 66288472..0f348657 100644 --- a/spring-data-testapp/src/main/java/com/example/demo/CmdRunner.java +++ b/spring-data-testapp/src/main/java/com/example/demo/CmdRunner.java @@ -15,12 +15,12 @@ */ package com.example.demo; -import com.couchbase.client.java.transactions.TransactionResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; -import org.springframework.data.couchbase.CouchbaseClientFactory; import org.springframework.data.couchbase.core.CouchbaseTemplate; +import org.springframework.data.couchbase.transaction.error.TransactionSystemUnambiguousException; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; /** * Components of the type CommandLineRunner are called right after the application start up. So the method *run* is @@ -31,52 +31,70 @@ import org.springframework.stereotype.Component; @Component public class CmdRunner implements CommandLineRunner { - @Autowired AirportRepository airportRepository; @Autowired CouchbaseTemplate template; - @Autowired CouchbaseClientFactory couchbaseClientFactory; - @Autowired AirportService airportService; + @Autowired AirlineGatesService airlineGatesService; @Override - public void run(String... strings) throws Exception { + public void run(String... strings) { + try { // remove leftovers from previous run + template.removeById(AirlineGates.class).one("1"); + } catch (Exception e) {} try { - template.removeById(Airport.class).one("1"); - } catch (Exception e){} + template.removeById(AirlineGates.class).one("2"); + } catch (Exception e) {} + + AirlineGates airlineGates1 = new AirlineGates("1", "JFK", "American Airlines", Long.valueOf(200)); //1 + AirlineGates airlineGates2 = new AirlineGates("2", "JFK", "Lufthansa", Long.valueOf(200)); + AirlineGates saved1 = airlineGatesService.save(airlineGates1); + AirlineGates saved2 = airlineGatesService.save(airlineGates2); + AirlineGates found1 = airlineGatesService.findById(saved1.getId()); //2 + AirlineGates found2 = airlineGatesService.findById(saved2.getId()); + System.err.println("initialized airlines"); + System.err.println(" found before transferGates: " + found1); + System.err.println(" found before transferGates: " + found2); + System.err.println("this transferGates attempt will succeed"); + // move 50 gates from airline1 to airline2 + int gatesToTransfer=50; + airlineGatesService.transferGates(airlineGates1.getId(), airlineGates2.getId(), gatesToTransfer, null); //3 + found1 = airlineGatesService.findById(saved1.getId()); + found2 = airlineGatesService.findById(saved2.getId()); + System.err.println(" found after transferGates: " + found1); //4 + System.err.println(" found after transferGates: " + found2); + Assert.isTrue(found1.getGates().equals(airlineGates1.getGates()-gatesToTransfer), "should have transferred"); + Assert.isTrue(found2.getGates().equals(airlineGates1.getGates()+gatesToTransfer), "should have transferred"); + System.err.println("this transferGates attempt will fail"); + // attempt to move 44 gates from airline1 to airline2, but it fails. try { - template.removeById(Airport.class).one("2"); - } catch (Exception e){} - - Airport new_1 = new Airport("1", "JFK", "jfk"); - Airport saved_1 = airportRepository.save(new_1); - Airport found_1 = airportRepository.findById(saved_1.getId()).get(); - System.out.println("found using repository by id: " + found_1); - - Airport new_2 = new Airport("2", "LGA", "lga"); - Airport saved_2 = airportRepository.save(new_2); - Airport found_2 = airportRepository.findById(saved_2.getId()).get(); - System.out.println("found using repository by id: " + found_2); - Airport found_3 = airportRepository.findByIata("JFK"); - System.out.println("founding using repository findByIata: "+found_3); - - - airportService.transferGates(new_1.getId(), new_2.getId(), 50); - - System.out.println("found after transferGates: "+airportRepository.findById(saved_1.getId()).get()); - System.out.println("found after transferGates: "+airportRepository.findById(saved_2.getId()).get()); - } - - - public void transferGatesDeprecated(String fromId, String toId, int gatesToTransfer) { - TransactionResult txResult = template.getCouchbaseClientFactory().getCluster().transactions().run(ctx -> { - - Airport fromAirport = template.findById(Airport.class).one(fromId); - Airport toAirport = template.findById(Airport.class).one(toId); - toAirport.gates += gatesToTransfer; - fromAirport.gates -= gatesToTransfer; - template.save(fromAirport); - template.save(toAirport); - }); - + // 5 + airlineGatesService.transferGates(airlineGates1.getId(), airlineGates2.getId(), 44, new SimulateErrorException()); + } catch (RuntimeException rte) { + if (!(rte instanceof TransactionSystemUnambiguousException) && rte != null + && rte.getCause() instanceof SimulateErrorException) { + throw rte; + } + System.err.println(" got exception "+rte); + } + System.err.println(" found after transferGates: " + airlineGatesService.findById(airlineGates1.getId())); + System.err.println(" found after transferGates: " + airlineGatesService.findById(airlineGates2.getId())); + Assert.isTrue(found1.getGates().equals(airlineGates1.getGates()-gatesToTransfer), "should be same as previous"); + Assert.isTrue(found2.getGates().equals(airlineGates1.getGates()+gatesToTransfer), "should be same as previous"); + System.err.println("this transferGates attempt will succeed"); + try { + // 5 + airlineGatesService.transferGatesReactive(airlineGates1.getId(), airlineGates2.getId(), 44, null).block(); + } catch (RuntimeException rte) { + if (!(rte instanceof TransactionSystemUnambiguousException) && rte != null + && rte.getCause() instanceof SimulateErrorException) { + throw rte; + } + System.err.println(" got exception "+rte); + } + System.err.println(" found after transferGates: " + airlineGatesService.findById(airlineGates1.getId())); + System.err.println(" found after transferGates: " + airlineGatesService.findById(airlineGates2.getId())); + Assert.isTrue(found1.getGates().equals(airlineGates1.getGates()-gatesToTransfer), "should have transferred"); + Assert.isTrue(found2.getGates().equals(airlineGates1.getGates()+gatesToTransfer), "should have transferred"); } + static class SimulateErrorException extends RuntimeException {} } diff --git a/spring-data-testapp/src/main/java/com/example/demo/Config.java b/spring-data-testapp/src/main/java/com/example/demo/Config.java index d368487c..40286eab 100644 --- a/spring-data-testapp/src/main/java/com/example/demo/Config.java +++ b/spring-data-testapp/src/main/java/com/example/demo/Config.java @@ -15,6 +15,7 @@ */ package com.example.demo; +import com.couchbase.client.core.msg.kv.DurabilityLevel; import com.couchbase.client.java.env.ClusterEnvironment; import com.couchbase.client.java.transactions.config.TransactionsConfig; import com.fasterxml.jackson.databind.ObjectMapper; @@ -22,6 +23,7 @@ import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.context.annotation.Configuration; import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration; import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; /** * @@ -29,7 +31,8 @@ import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepos * @author Michael Reiche */ @Configuration -@EnableCouchbaseRepositories({"com.example.demo", "com.wu.onep.ordnrt.cbviewsrch.repository"}) +@EnableCouchbaseRepositories({"com.example.demo"}) +@EnableTransactionManagement public class Config extends AbstractCouchbaseConfiguration { @Override public String getConnectionString() { @@ -53,7 +56,7 @@ public class Config extends AbstractCouchbaseConfiguration { @Override public void configureEnvironment(ClusterEnvironment.Builder builder){ - // builder.transactionsConfig(TransactionsConfig.durabilityLevel(DurabilityLevel.NONE)); + builder.transactionsConfig(TransactionsConfig.durabilityLevel(DurabilityLevel.NONE)); }