readonly-transaction-demo example added

This commit is contained in:
stvort
2021-07-17 01:58:18 +04:00
parent a8d2ae90e8
commit c3e77b712b
9 changed files with 270 additions and 0 deletions
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.otus</groupId>
<artifactId>readonly-transaction-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>readonly-transaction-demo</name>
<description>Readonly transaction demo</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,13 @@
package ru.otus.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ReadonlyTransactionDemoApplication {
public static void main(String[] args) {
SpringApplication.run(ReadonlyTransactionDemoApplication.class, args);
}
}
@@ -0,0 +1,23 @@
package ru.otus.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
}
@@ -0,0 +1,13 @@
package ru.otus.demo.repository;
import ru.otus.demo.model.Person;
import java.util.List;
public interface PersonRepository {
Person save(Person person);
List<Person> findAll();
Person findById(long id);
}
@@ -0,0 +1,43 @@
package ru.otus.demo.repository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import ru.otus.demo.model.Person;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import java.util.List;
@Repository
@RequiredArgsConstructor
public class PersonRepositoryJpa implements PersonRepository {
@PersistenceContext
private final EntityManager em;
@Override
public Person save(Person person) {
if (person.getId() == 0) {
Person savedPerson = new Person(person.getId(), person.getName());
em.persist(savedPerson);
return savedPerson;
}
return em.merge(person);
}
@Override
public List<Person> findAll() {
TypedQuery<Person> query = em.createQuery("select p from Person p", Person.class);
return query.getResultList();
}
@Override
public Person findById(long id) {
TypedQuery<Person> query = em.createQuery("select p from Person p where p.id = :id", Person.class);
query.setParameter("id", id);
return query.getSingleResult();
}
}
@@ -0,0 +1,36 @@
package ru.otus.demo.services;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ru.otus.demo.model.Person;
import ru.otus.demo.repository.PersonRepository;
@Service
public class PersonService {
private final PersonRepository personRepository;
public PersonService(PersonRepository personRepository) {
this.personRepository = personRepository;
}
public Person findById(long id) {
return personRepository.findById(id);
}
@Transactional
public void save(Person person){
personRepository.save(person);
}
@Transactional
public void updateWithNormalTran(long id, String name) {
Person person = personRepository.findById(id);
person.setName(name);
}
@Transactional(readOnly = true)
public void updateWithReadonlyTran(long id, String name) {
Person person = personRepository.findById(id);
person.setName(name);
}
}
@@ -0,0 +1,19 @@
spring:
datasource:
#url: jdbc:postgresql://localhost:5432/persons
#username: postgres
#password: postgres
url: jdbc:h2:mem:testdb
initialization-mode: always
jpa:
generate-ddl: false
hibernate:
ddl-auto: none
show-sql: true
properties:
hibernate:
#format_sql: true
@@ -0,0 +1,7 @@
drop table if exists person;
create table person (
id bigserial,
name varchar(200),
primary key(id)
);
@@ -0,0 +1,42 @@
package ru.otus.demo.services;
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.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ru.otus.demo.model.Person;
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 PersonServiceTest {
@Autowired
private PersonService personService;
@BeforeEach
void setUp() {
personService.save(new Person(0, "Igor"));
}
@Test
void updateWithNormalTran() {
personService.updateWithNormalTran(1, "Vasya");
Person actualPerson = personService.findById(1);
assertThat(actualPerson).extracting(Person::getName).isEqualTo("Vasya");
}
@Test
void updateWithReadonlyTran() {
personService.updateWithReadonlyTran(1, "Vasya");
Person actualPerson = personService.findById(1);
assertThat(actualPerson).extracting(Person::getName).isEqualTo("Igor");
}
}