* BAEL-6447: Persistable examples

* BAEL-6447: Explicit Repository Check Example

* BAEL-6447: Reformatting

* BAEL-6447: Renamed the method

* BAEL-6447: Parametrize the repository

* BAEL-6447: Added Author example for UnapdatableBook

* BAEL-6447: Remove findByTitleMethod

* BAEL-6447: Reformatting

* BAEL-6447: Service Test
This commit is contained in:
Eugene Kovko 2024-01-05 23:38:36 +01:00 committed by GitHub
parent d3e944a159
commit e2b376516e
23 changed files with 732 additions and 0 deletions

View File

@ -0,0 +1,8 @@
package com.baeldung.spring.insertableonly;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
}

View File

@ -0,0 +1,37 @@
package com.baeldung.spring.insertableonly.entitymanager;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class EntityManagerBook {
@Id
@GeneratedValue
private Long id;
private String title;
public EntityManagerBook() {
}
public EntityManagerBook(String title) {
this.title = title;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.spring.insertableonly.entitymanager;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EntityManagerBookRepository extends JpaRepository<EntityManagerBook, Long>,
PersistableEntityManagerBookRepository<EntityManagerBook> {
}

View File

@ -0,0 +1,5 @@
package com.baeldung.spring.insertableonly.entitymanager;
public interface PersistableEntityManagerBookRepository<S> {
S persist(S entity);
}

View File

@ -0,0 +1,18 @@
package com.baeldung.spring.insertableonly.entitymanager;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
public class PersistableEntityManagerBookRepositoryImpl<S> implements PersistableEntityManagerBookRepository<S> {
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public S persist(S entity) {
entityManager.persist(entity);
return entity;
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.spring.insertableonly.persistable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.springframework.data.domain.Persistable;
@Entity
public class PersistableBook implements Persistable<Long> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
public PersistableBook() {
}
public PersistableBook(String title) {
this.title = title;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
@Override
public boolean isNew() {
return true;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.spring.insertableonly.persistable;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PersistableBookRepository extends JpaRepository<PersistableBook, Long> {
}

View File

@ -0,0 +1,36 @@
package com.baeldung.spring.insertableonly.query;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class CustomQueryBook {
@Id
private Long id;
private String title;
public CustomQueryBook() {
}
public CustomQueryBook(long id, String title) {
this.id = id;
this.title = title;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.spring.insertableonly.query;
import javax.transaction.Transactional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface CustomQueryBookRepository extends JpaRepository<CustomQueryBook, Long> {
@Modifying
@Transactional
@Query(value = "INSERT INTO custom_query_book (id, title) VALUES (:#{#book.id}, :#{#book.title})",
nativeQuery = true)
void persist(@Param("book") CustomQueryBook book);
}

View File

@ -0,0 +1,37 @@
package com.baeldung.spring.insertableonly.repositorycheck;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class RepositoryCheckBook {
@Id
@GeneratedValue
private Long id;
private String title;
public RepositoryCheckBook() {
}
public RepositoryCheckBook(String title) {
this.title = title;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.spring.insertableonly.repositorycheck;
import org.springframework.data.jpa.repository.JpaRepository;
public interface RepositoryCheckBookRepository extends JpaRepository<RepositoryCheckBook, Long> {
default <S extends RepositoryCheckBook> S persist(S entity) {
if (entity.getId() == null) {
return save(entity);
}
return entity;
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.spring.insertableonly.simple;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class SimpleBook {
@Id
@GeneratedValue
private Long id;
private String title;
public SimpleBook() {
}
public SimpleBook(String title) {
this.title = title;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.spring.insertableonly.simple;
import org.springframework.data.jpa.repository.JpaRepository;
public interface SimpleBookRepository extends JpaRepository<SimpleBook, Long> {
}

View File

@ -0,0 +1,28 @@
package com.baeldung.spring.insertableonly.simple;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SimpleBookService {
private SimpleBookRepository repository;
@Autowired
public SimpleBookService(SimpleBookRepository repository) {
this.repository = repository;
}
public SimpleBook save(SimpleBook book) {
if (book.getId() == null) {
return repository.save(book);
}
return book;
}
public Optional<SimpleBook> findById(Long id) {
return repository.findById(id);
}
}

View File

@ -0,0 +1,50 @@
package com.baeldung.spring.insertableonly.unpadatable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class UnapdatableBook {
@Id
@GeneratedValue
private Long id;
@Column(updatable = false)
private String title;
private String author;
public UnapdatableBook() {
}
public UnapdatableBook(String title, String author) {
this.title = title;
this.author = author;
}
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.spring.insertableonly.unpadatable;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UnapdatableBookRepository extends JpaRepository<UnapdatableBook, Long> {
}

View File

@ -0,0 +1,11 @@
package com.baeldung.spring.insertableonly;
public interface ConstantHolder {
String TITLE = "Pet Cemetery";
String NEW_TITLE = "Pet Sematary";
String AUTHOR = "B.B. King";
String NEW_AUTHOR = "Stephen King";
long ID = 1L;
}

View File

@ -0,0 +1,58 @@
package com.baeldung.spring.insertableonly;
import static com.baeldung.spring.insertableonly.ConstantHolder.ID;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_TITLE;
import static com.baeldung.spring.insertableonly.ConstantHolder.TITLE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.baeldung.spring.insertableonly.query.CustomQueryBook;
import com.baeldung.spring.insertableonly.query.CustomQueryBookRepository;
import java.util.Optional;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataIntegrityViolationException;
@SpringBootTest(classes = Application.class, properties = {
"spring.datasource.url=jdbc:h2:mem:~/test;DATABASE_TO_UPPER=false"
})
class CustomQueryBookRepositoryIntegrationTest {
@Autowired
private CustomQueryBookRepository repository;
@BeforeEach
void setup() {
repository.deleteAll();
}
@Test
void givenDatasourceWhenSaveBookThenBookPersisted() {
CustomQueryBook book = new CustomQueryBook(ID, TITLE);
repository.persist(book);
CustomQueryBook persistedBook = getBookById(ID);
assertThat(persistedBook.getId()).isEqualTo(ID);
assertThat(persistedBook.getTitle()).isEqualTo(TITLE);
}
@Test
void givenDatasourceWhenUpdateThenThrowException() {
CustomQueryBook book = new CustomQueryBook(ID, TITLE);
repository.persist(book);
CustomQueryBook persistedBook = getBookById(ID);
persistedBook.setTitle(NEW_TITLE);
assertThatExceptionOfType(DataIntegrityViolationException.class)
.isThrownBy(() -> repository.persist(persistedBook));
}
private CustomQueryBook getBookById(long id) {
Optional<CustomQueryBook> book = repository.findById(id);
assertTrue(book.isPresent());
return book.get();
}
}

View File

@ -0,0 +1,53 @@
package com.baeldung.spring.insertableonly;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_TITLE;
import static com.baeldung.spring.insertableonly.ConstantHolder.TITLE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.baeldung.spring.insertableonly.entitymanager.EntityManagerBook;
import com.baeldung.spring.insertableonly.entitymanager.EntityManagerBookRepository;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@SpringBootTest(classes = Application.class)
class EntityMangerBookRepositoryIntegrationTest {
@Autowired
private EntityManagerBookRepository repository;
@BeforeEach
void setup() {
repository.deleteAll();
}
@Test
void givenDatasourceWhenSaveBookThenBookPersisted() {
EntityManagerBook newBook = new EntityManagerBook(TITLE);
EntityManagerBook persistedBook = repository.persist(newBook);
assertThat(persistedBook.getId()).isNotNull();
Long id = persistedBook.getId();
EntityManagerBook actualBook = getBookById(id);
assertThat(actualBook.getId()).isEqualTo(id);
assertThat(actualBook.getTitle()).isEqualTo(TITLE);
}
@Test
void givenDatasourceWhenUpdateThenThrowException() {
EntityManagerBook book = new EntityManagerBook(TITLE);
EntityManagerBook persistedBook = repository.persist(book);
persistedBook.setTitle(NEW_TITLE);
assertThatExceptionOfType(InvalidDataAccessApiUsageException.class)
.isThrownBy(() -> repository.persist(persistedBook));
}
private EntityManagerBook getBookById(long id) {
Optional<EntityManagerBook> book = repository.findById(id);
assertTrue(book.isPresent());
return book.get();
}
}

View File

@ -0,0 +1,55 @@
package com.baeldung.spring.insertableonly;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_TITLE;
import static com.baeldung.spring.insertableonly.ConstantHolder.TITLE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.baeldung.spring.insertableonly.persistable.PersistableBook;
import com.baeldung.spring.insertableonly.persistable.PersistableBookRepository;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.InvalidDataAccessApiUsageException;
@SpringBootTest(classes = Application.class)
class PersistableBookRepositoryIntegrationTest {
@Autowired
private PersistableBookRepository repository;
@BeforeEach
void setup() {
repository.deleteAll();
}
@Test
void givenDatasourceWhenSaveBookThenBookPersisted() {
PersistableBook newBook = new PersistableBook(TITLE);
PersistableBook persistedBook = repository.save(newBook);
assertThat(persistedBook.getId()).isNotNull();
Long id = persistedBook.getId();
PersistableBook actualBook = getBookById(id);
assertThat(actualBook.getTitle()).isEqualTo(TITLE);
assertThat(actualBook.getId()).isEqualTo(id);
}
@Test
void givenDatasourceWhenUpdateThenThrowException() {
PersistableBook book = new PersistableBook(TITLE);
PersistableBook persistedBook = repository.save(book);
persistedBook.setTitle(NEW_TITLE);
assertThatExceptionOfType(InvalidDataAccessApiUsageException.class)
.isThrownBy(() -> repository.save(persistedBook));
}
private PersistableBook getBookById(long id) {
Optional<PersistableBook> book = repository.findById(id);
assertTrue(book.isPresent());
return book.get();
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.spring.insertableonly;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_TITLE;
import static com.baeldung.spring.insertableonly.ConstantHolder.TITLE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.baeldung.spring.insertableonly.repositorycheck.RepositoryCheckBook;
import com.baeldung.spring.insertableonly.repositorycheck.RepositoryCheckBookRepository;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = Application.class)
class RepositoryCheckBookRepositoryIntegrationTest {
@Autowired
private RepositoryCheckBookRepository repository;
@BeforeEach
void setup() {
repository.deleteAll();
}
@Test
void givenDatasourceWhenSaveBookThenBookPersisted() {
RepositoryCheckBook newBook = new RepositoryCheckBook(TITLE);
RepositoryCheckBook persistedBook = repository.persist(newBook);
Long id = persistedBook.getId();
assertThat(id).isNotNull();
RepositoryCheckBook actualBook = getBookById(id);
assertThat(actualBook.getTitle()).isEqualTo(TITLE);
assertThat(actualBook.getId()).isEqualTo(id);
}
@Test
void givenDatasourceWhenUpdateBookThenUpdatedIsIgnored() {
RepositoryCheckBook book = new RepositoryCheckBook(TITLE);
RepositoryCheckBook persistedBook = repository.persist(book);
Long id = persistedBook.getId();
persistedBook.setTitle(NEW_TITLE);
repository.persist(persistedBook);
Optional<RepositoryCheckBook> actualBook = repository.findById(id);
assertTrue(actualBook.isPresent());
assertThat(actualBook.get().getId()).isEqualTo(id);
assertThat(actualBook.get().getTitle()).isEqualTo(TITLE);
}
private RepositoryCheckBook getBookById(long id) {
Optional<RepositoryCheckBook> book = repository.findById(id);
assertTrue(book.isPresent());
return book.get();
}
}

View File

@ -0,0 +1,76 @@
package com.baeldung.spring.insertableonly;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_TITLE;
import static com.baeldung.spring.insertableonly.ConstantHolder.TITLE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.baeldung.spring.insertableonly.simple.SimpleBook;
import com.baeldung.spring.insertableonly.simple.SimpleBook;
import com.baeldung.spring.insertableonly.simple.SimpleBookRepository;
import com.baeldung.spring.insertableonly.simple.SimpleBookService;
import java.util.Optional;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = Application.class)
class SimpleBookRepositoryIntegrationTest {
@Autowired
private SimpleBookRepository repository;
@Autowired
private SimpleBookService service;
@BeforeEach
void setup() {
repository.deleteAll();
}
@Test
void givenDatasourceWhenSaveBookThenBookPersisted() {
SimpleBook newBook = new SimpleBook(TITLE);
SimpleBook persistedBook = repository.save(newBook);
Long id = persistedBook.getId();
assertThat(id).isNotNull();
SimpleBook actualBook = getBookById(id);
assertThat(actualBook.getTitle()).isEqualTo(TITLE);
assertThat(actualBook.getId()).isEqualTo(id);
}
@Test
void givenDatasourceWhenUpdateBookThenBookIsUpdated() {
SimpleBook book = new SimpleBook(TITLE);
SimpleBook persistedBook = repository.save(book);
Long id = persistedBook.getId();
persistedBook.setTitle(NEW_TITLE);
repository.save(persistedBook);
Optional<SimpleBook> actualBook = repository.findById(id);
assertTrue(actualBook.isPresent());
assertThat(actualBook.get().getId()).isEqualTo(id);
assertThat(actualBook.get().getTitle()).isEqualTo(NEW_TITLE);
}
@Test
void givenDatasourceWhenUpdateBookThenUpdatedIsIgnored() {
SimpleBook book = new SimpleBook(TITLE);
SimpleBook persistedBook = service.save(book);
Long id = persistedBook.getId();
persistedBook.setTitle(NEW_TITLE);
service.save(persistedBook);
Optional<SimpleBook> actualBook = service.findById(id);
assertTrue(actualBook.isPresent());
assertThat(actualBook.get().getId()).isEqualTo(id);
assertThat(actualBook.get().getTitle()).isEqualTo(TITLE);
}
private SimpleBook getBookById(long id) {
Optional<SimpleBook> book = repository.findById(id);
assertTrue(book.isPresent());
return book.get();
}
}

View File

@ -0,0 +1,64 @@
package com.baeldung.spring.insertableonly;
import static com.baeldung.spring.insertableonly.ConstantHolder.AUTHOR;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_AUTHOR;
import static com.baeldung.spring.insertableonly.ConstantHolder.NEW_TITLE;
import static com.baeldung.spring.insertableonly.ConstantHolder.TITLE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.baeldung.spring.insertableonly.unpadatable.UnapdatableBook;
import com.baeldung.spring.insertableonly.unpadatable.UnapdatableBook;
import com.baeldung.spring.insertableonly.unpadatable.UnapdatableBookRepository;
import java.util.Optional;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = Application.class)
class UnapdatableBookRepositoryIntegrationTest {
@Autowired
private UnapdatableBookRepository repository;
@BeforeEach
void setup() {
repository.deleteAll();
}
@Test
void givenDatasourceWhenSaveBookThenBookPersisted() {
UnapdatableBook newBook = new UnapdatableBook(TITLE, AUTHOR);
UnapdatableBook persistedBook = repository.save(newBook);
Long id = persistedBook.getId();
assertThat(id).isNotNull();
UnapdatableBook actualBook = getBookById(id);
assertThat(actualBook.getId()).isEqualTo(id);
assertThat(actualBook.getTitle()).isEqualTo(TITLE);
assertThat(actualBook.getAuthor()).isEqualTo(AUTHOR);
}
@Test
void givenDatasourceWhenUpdateBookTheBookUpdatedIgnored() {
UnapdatableBook book = new UnapdatableBook(TITLE, AUTHOR);
UnapdatableBook persistedBook = repository.save(book);
Long id = persistedBook.getId();
persistedBook.setTitle(NEW_TITLE);
persistedBook.setAuthor(NEW_AUTHOR);
repository.save(persistedBook);
Optional<UnapdatableBook> actualBook = repository.findById(id);
assertTrue(actualBook.isPresent());
assertThat(actualBook.get().getId()).isEqualTo(id);
assertThat(actualBook.get().getTitle()).isEqualTo(TITLE);
assertThat(actualBook.get().getAuthor()).isEqualTo(NEW_AUTHOR);
}
private UnapdatableBook getBookById(long id) {
Optional<UnapdatableBook> book = repository.findById(id);
assertTrue(book.isPresent());
return book.get();
}
}