diff --git a/examples/readonly-transaction-demo/src/main/java/ru/otus/demo/repository/PersonRepositoryJpa.java b/examples/readonly-transaction-demo/src/main/java/ru/otus/demo/repository/PersonRepositoryJpa.java index fc699a67..5aee7bad 100644 --- a/examples/readonly-transaction-demo/src/main/java/ru/otus/demo/repository/PersonRepositoryJpa.java +++ b/examples/readonly-transaction-demo/src/main/java/ru/otus/demo/repository/PersonRepositoryJpa.java @@ -1,6 +1,7 @@ package ru.otus.demo.repository; import lombok.RequiredArgsConstructor; +import org.hibernate.Session; import org.springframework.stereotype.Repository; import ru.otus.demo.model.Person; @@ -35,9 +36,13 @@ public class PersonRepositoryJpa implements PersonRepository { @Override public Person findById(long id) { + System.out.println("FlushMode: " + em.unwrap(Session.class).getHibernateFlushMode()); + return em.find(Person.class, id); +/* TypedQuery query = em.createQuery("select p from Person p where p.id = :id", Person.class); query.setParameter("id", id); return query.getSingleResult(); +*/ } } diff --git a/examples/readonly-transaction-demo/src/main/resources/application.yml b/examples/readonly-transaction-demo/src/main/resources/application.yml index 9ddf5b1e..99cf96dd 100644 --- a/examples/readonly-transaction-demo/src/main/resources/application.yml +++ b/examples/readonly-transaction-demo/src/main/resources/application.yml @@ -16,4 +16,8 @@ spring: show-sql: true properties: hibernate: - #format_sql: true \ No newline at end of file + #format_sql: true + +logging: + level: + org.hibernate.engine.transaction.internal: DEBUG \ No newline at end of file diff --git a/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/PersonServiceTest.java b/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/PersonServiceTest.java index 1069ea0a..9576a876 100644 --- a/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/PersonServiceTest.java +++ b/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/PersonServiceTest.java @@ -27,6 +27,17 @@ class PersonServiceTest { personService.save(new Person(0, "Igor", new Email(0, "noname@nomail.ru"))); } + /* + // Изменение имени пёрсона внутри updateWithNormalTran ПОПАДАЮТ в БД после закрытия сессии/транзакции + // Работаем в обычной транзакции (в логах есть ее начало и коммит, а так же update) + // FlushMode: AUTO (есть в логах) + + 2021-07-24 19:21:16.310 DEBUG 8636 --- [ main] o.h.e.t.internal.TransactionImpl : begin + Hibernate: select person0_.id as id1_1_, person0_.email_id as email_id3_1_, person0_.name as name2_1_ from person person0_ where person0_.id=? + Hibernate: select email0_.id as id1_0_0_, email0_.address as address2_0_0_ from email email0_ where email0_.id=? + 2021-07-24 19:21:16.390 DEBUG 8636 --- [ main] o.h.e.t.internal.TransactionImpl : committing + Hibernate: update person set email_id=?, name=? where id=? + */ @Test void updateWithNormalTran() { personService.updateWithNormalTran(1, "Vasya"); @@ -34,6 +45,17 @@ class PersonServiceTest { assertThat(actualPerson).extracting(Person::getName).isEqualTo("Vasya"); } + /* + // Работаем в readonly транзакции (в логах есть ее начало и коммит) + // Изменение имени пёрсона внутри updateWithReadonlyTran НЕ попадают в БД после закрытия сессии/транзакции + // FlushMode: MANUAL (есть в логах), поэтому изменения и не попадают + + 2021-07-24 19:15:22.889 DEBUG 11024 --- [ main] o.h.e.t.internal.TransactionImpl : begin + Hibernate: select person0_.id as id1_1_, person0_.email_id as email_id3_1_, person0_.name as name2_1_ from person person0_ where person0_.id=? + Hibernate: select email0_.id as id1_0_0_, email0_.address as address2_0_0_ from email email0_ where email0_.id=? + 2021-07-24 19:15:22.967 DEBUG 11024 --- [ main] o.h.e.t.internal.TransactionImpl : committing + + */ @Test void updateWithReadonlyTran() { personService.updateWithReadonlyTran(1, "Vasya"); @@ -41,6 +63,14 @@ class PersonServiceTest { assertThat(actualPerson).extracting(Person::getName).isEqualTo("Igor"); } + /* + // Работаем без транзакции (в логах нет ее начала и коммита) + // Изменение имени пёрсона внутри updateWithoutTran НЕ попадают в БД после закрытия сессии/транзакции + // FlushMode: AUTO (есть в логах) + + Hibernate: select person0_.id as id1_1_, person0_.email_id as email_id3_1_, person0_.name as name2_1_ from person person0_ where person0_.id=? + Hibernate: select email0_.id as id1_0_0_, email0_.address as address2_0_0_ from email email0_ where email0_.id=? + */ @Test void updateWithoutTran() { personService.updateWithoutTran(1, "Vasya"); diff --git a/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/TransactionsTest.java b/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/TransactionsTest.java new file mode 100644 index 00000000..505ff189 --- /dev/null +++ b/examples/readonly-transaction-demo/src/test/java/ru/otus/demo/services/TransactionsTest.java @@ -0,0 +1,83 @@ +package ru.otus.demo.services; + +import org.hibernate.FlushMode; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.transaction.TransactionManager; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionTemplate; +import ru.otus.demo.model.Email; +import ru.otus.demo.model.Person; + +import javax.persistence.EntityManager; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@SpringBootTest +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@Transactional(propagation = Propagation.NOT_SUPPORTED) +@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) +class TransactionsTest { + + private static final Person expectedPerson = new Person(1L, "Igor", + new Email(1L, "noname@nomail.ru")); + + @Autowired + private SessionFactory sf; + + @Autowired + private Session s; + + @Autowired + private TransactionTemplate tm; + + @BeforeEach + void setUp() { + tm.setReadOnly(false); + tm.execute(status -> { + s.persist(new Person(0, expectedPerson.getName(), + new Email(0, expectedPerson.getEmail().getAddress()))); + return null; + }); + + sf.getStatistics().setStatisticsEnabled(true); + sf.getStatistics().clear(); + } + + @Test + void findWithNormalTran() { + tm.setReadOnly(false); + Person actualPerson = tm.execute(status -> { + assertThat(s.getHibernateFlushMode()).isEqualTo(FlushMode.AUTO); + return s.find(Person.class, 1L); + }); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + assertThat(sf.getStatistics().getTransactionCount()).isEqualTo(1); + } + + @Test + void findWithReadOnlyTran() { + tm.setReadOnly(true); + Person actualPerson = tm.execute(status -> { + assertThat(s.getHibernateFlushMode()).isEqualTo(FlushMode.MANUAL); + return s.find(Person.class, 1L); + }); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + assertThat(sf.getStatistics().getTransactionCount()).isEqualTo(1); + } + + @Test + void findWithoutTran() { + assertThat(s.getHibernateFlushMode()).isEqualTo(FlushMode.AUTO); + Person actualPerson = s.find(Person.class, 1L); + assertThat(actualPerson).usingRecursiveComparison().isEqualTo(expectedPerson); + assertThat(sf.getStatistics().getTransactionCount()).isEqualTo(0); + } +} \ No newline at end of file diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java index abdf6183..f039a8c8 100644 --- a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/integration/IntegrationConfig.java @@ -1,6 +1,5 @@ package ru.otus.example.springmail_integration_demo.integration; -import lombok.val; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -10,7 +9,6 @@ import org.springframework.integration.dsl.IntegrationFlowDefinition; import org.springframework.integration.dsl.MessageChannels; import org.springframework.integration.dsl.Pollers; import org.springframework.integration.scheduling.PollerMetadata; -import org.springframework.mail.SimpleMailMessage; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.messaging.Message; import org.springframework.messaging.PollableChannel; diff --git a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java index a14d2ca8..ceaac606 100644 --- a/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java +++ b/examples/spring-mail-integration-demo/src/main/java/ru/otus/example/springmail_integration_demo/services/ActivityStatCalculationEmitterSerivce.java @@ -4,16 +4,12 @@ import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import ru.otus.example.springmail_integration_demo.integration.ActivityStatGateway; -import ru.otus.example.springmail_integration_demo.repositories.ActivityTypeRepository; -import ru.otus.example.springmail_integration_demo.repositories.AppUserRepository; @RequiredArgsConstructor @Service public class ActivityStatCalculationEmitterSerivce { private static final String EMPTY_EXT_INFO = "none"; - private final ActivityTypeRepository activityTypeRepository; - private final AppUserRepository appUserRepository; private final ActivityStatGateway activityStatGateway; @Scheduled(initialDelay = 3000, fixedRate = 10000) diff --git a/examples/spring-mail-rabbitmq-demo/user-activity-processor-microservice/src/main/java/ru/otus/example/rabbitmq/rabbitmq/RabbitMqListener.java b/examples/spring-mail-rabbitmq-demo/user-activity-processor-microservice/src/main/java/ru/otus/example/rabbitmq/rabbitmq/RabbitMqListener.java index 4e390d31..6868dd9f 100644 --- a/examples/spring-mail-rabbitmq-demo/user-activity-processor-microservice/src/main/java/ru/otus/example/rabbitmq/rabbitmq/RabbitMqListener.java +++ b/examples/spring-mail-rabbitmq-demo/user-activity-processor-microservice/src/main/java/ru/otus/example/rabbitmq/rabbitmq/RabbitMqListener.java @@ -28,7 +28,7 @@ public class RabbitMqListener { val userActivity = objectMapper.readValue(message, UserActivity.class); val mailMessage = messageTransformer.transform(userActivity); - //System.out.println("Как будто посылаем письмо: " + mailMessage); + System.out.println("Как будто посылаем письмо: " + mailMessage); //mailSender.send(mailMessage); } @@ -46,7 +46,7 @@ public class RabbitMqListener { @RabbitListener(queues = "stat-calc-commands-queue") public void processStatCalcCommandsMessages(String message) { - //System.out.println("RECEIVED FROM stat-calc-commands-queue: " + message); + System.out.println("RECEIVED FROM stat-calc-commands-queue: " + message); activityStatRepository.deleteAll(); val activityStat = activityStatRepository.calcActivityStat();