JAVA-66: New module spring-data-jpa-crud
This commit is contained in:
parent
92b1c62c1a
commit
2ca8ec847c
|
@ -0,0 +1,21 @@
|
||||||
|
## Spring Data JPA - CRUD
|
||||||
|
|
||||||
|
This module contains articles about CRUD operations in Spring Data JPA
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
- [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby)
|
||||||
|
- [Spring Data JPA Delete and Relationships](https://www.baeldung.com/spring-data-jpa-delete)
|
||||||
|
- [INSERT Statement in JPA](https://www.baeldung.com/jpa-insert)
|
||||||
|
- [Spring Data JPA Batch Inserts](https://www.baeldung.com/spring-data-jpa-batch-inserts)
|
||||||
|
- [Batch Insert/Update with Hibernate/JPA](https://www.baeldung.com/jpa-hibernate-batch-insert-update)
|
||||||
|
- [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush)
|
||||||
|
- [Generate Database Schema with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-generate-db-schema)
|
||||||
|
|
||||||
|
### Eclipse Config
|
||||||
|
After importing the project into Eclipse, you may see the following error:
|
||||||
|
"No persistence xml file found in project"
|
||||||
|
|
||||||
|
This can be ignored:
|
||||||
|
- Project -> Properties -> Java Persistance -> JPA -> Error/Warnings -> Select Ignore on "No persistence xml file found in project"
|
||||||
|
Or:
|
||||||
|
- Eclipse -> Preferences - Validation - disable the "Build" execution of the JPA Validator
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?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
|
||||||
|
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-data-jpa-crud</artifactId>
|
||||||
|
<name>spring-data-jpa-crud</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-2</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-2</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Prod Dependencies -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>${guava.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.ttddyy</groupId>
|
||||||
|
<artifactId>datasource-proxy</artifactId>
|
||||||
|
<version>${datasource-proxy.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Test containers only dependencies -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testcontainers</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>${testcontainers.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- Test containers only dependencies -->
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<datasource-proxy.version>1.4.1</datasource-proxy.version>
|
||||||
|
<guava.version>21.0</guava.version>
|
||||||
|
<testcontainers.version>1.12.2</testcontainers.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableJpaRepositories
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.baeldung.batchinserts;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||||
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
|
import org.aopalliance.intercept.MethodInvocation;
|
||||||
|
import org.springframework.aop.framework.ProxyFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Profile("batchinserts")
|
||||||
|
public class DatasourceProxyBeanPostProcessor implements BeanPostProcessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
|
||||||
|
if (bean instanceof DataSource) {
|
||||||
|
ProxyFactory factory = new ProxyFactory(bean);
|
||||||
|
factory.setProxyTargetClass(true);
|
||||||
|
factory.addAdvice(new ProxyDataSourceInterceptor((DataSource) bean));
|
||||||
|
return factory.getProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ProxyDataSourceInterceptor implements MethodInterceptor {
|
||||||
|
|
||||||
|
private final DataSource dataSource;
|
||||||
|
|
||||||
|
public ProxyDataSourceInterceptor(final DataSource dataSource) {
|
||||||
|
this.dataSource = ProxyDataSourceBuilder.create(dataSource).name("Batch-Insert-Logger").asJson().countQuery().logQueryToSysOut().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(final MethodInvocation invocation) throws Throwable {
|
||||||
|
Method proxyMethod = ReflectionUtils.findMethod(dataSource.getClass(), invocation.getMethod().getName());
|
||||||
|
if (proxyMethod != null) {
|
||||||
|
return proxyMethod.invoke(dataSource, invocation.getArguments());
|
||||||
|
}
|
||||||
|
return invocation.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package com.baeldung.batchinserts.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class School {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "school")
|
||||||
|
private List<Student> students;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Student> getStudents() {
|
||||||
|
return students;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStudents(List<Student> students) {
|
||||||
|
this.students = students;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.baeldung.batchinserts.model;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Student {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private School school;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public School getSchool() {
|
||||||
|
return school;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSchool(School school) {
|
||||||
|
this.school = school;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung.boot;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableJpaRepositories("com.baeldung")
|
||||||
|
@EntityScan("com.baeldung")
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.boot.daos;
|
||||||
|
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.baeldung.boot.domain.Customer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JPA CrudRepository interface
|
||||||
|
*
|
||||||
|
* @author ysharma2512
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
@Transactional
|
||||||
|
public interface CustomerRepository extends CrudRepository<Customer, Long>{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.boot.daos.impl;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import com.baeldung.boot.domain.Person;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class PersonInsertRepository {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void insertWithQuery(Person person) {
|
||||||
|
entityManager.createNativeQuery("INSERT INTO person (id, first_name, last_name) VALUES (?,?,?)")
|
||||||
|
.setParameter(1, person.getId())
|
||||||
|
.setParameter(2, person.getFirstName())
|
||||||
|
.setParameter(3, person.getLastName())
|
||||||
|
.executeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void insertWithEntityManager(Person person) {
|
||||||
|
this.entityManager.persist(person);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.baeldung.boot.domain;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Customer Entity class
|
||||||
|
* @author ysharma2512
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
public class Customer {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public Customer(String firstName, String lastName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package com.baeldung.boot.domain;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(Long id, String firstName, String lastName) {
|
||||||
|
this.id = id;
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.baeldung.boot.web.controllers;
|
||||||
|
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.baeldung.boot.daos.CustomerRepository;
|
||||||
|
import com.baeldung.boot.domain.Customer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple controller to test the JPA CrudRepository operations
|
||||||
|
* controllers
|
||||||
|
*
|
||||||
|
* @author ysharma2512
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class CustomerController {
|
||||||
|
|
||||||
|
CustomerRepository customerRepository;
|
||||||
|
|
||||||
|
public CustomerController(CustomerRepository customerRepository2) {
|
||||||
|
this.customerRepository = customerRepository2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/customers")
|
||||||
|
public ResponseEntity<List<Customer>> insertCustomers() throws URISyntaxException {
|
||||||
|
Customer c1 = new Customer("James", "Gosling");
|
||||||
|
Customer c2 = new Customer("Doug", "Lea");
|
||||||
|
Customer c3 = new Customer("Martin", "Fowler");
|
||||||
|
Customer c4 = new Customer("Brian", "Goetz");
|
||||||
|
List<Customer> customers = Arrays.asList(c1, c2, c3, c4);
|
||||||
|
customerRepository.saveAll(customers);
|
||||||
|
return ResponseEntity.ok(customers);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package com.baeldung.datajpadelete.entity;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private Category category;
|
||||||
|
|
||||||
|
public Book() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Book(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Book(String title, Category category) {
|
||||||
|
this.title = title;
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategory(Category category) {
|
||||||
|
this.category = category;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.baeldung.datajpadelete.entity;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Category {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private List<Book> books;
|
||||||
|
|
||||||
|
public Category() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category(String name, Book... books) {
|
||||||
|
this.name = name;
|
||||||
|
this.books = Stream.of(books).collect(Collectors.toList());
|
||||||
|
this.books.forEach(x -> x.setCategory(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Category(String name, List<Book> books) {
|
||||||
|
this.name = name;
|
||||||
|
this.books = books;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Book> getBooks() {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBooks(List<Book> books) {
|
||||||
|
this.books = books;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.datajpadelete.repository;
|
||||||
|
|
||||||
|
import com.baeldung.datajpadelete.entity.Book;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface BookRepository extends CrudRepository<Book, Long> {
|
||||||
|
|
||||||
|
long deleteByTitle(String title);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("delete from Book b where b.title=:title")
|
||||||
|
void deleteBooks(@Param("title") String title);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.datajpadelete.repository;
|
||||||
|
|
||||||
|
import com.baeldung.datajpadelete.entity.Category;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface CategoryRepository extends CrudRepository<Category, Long> {
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.entity;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Employee {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Employee() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Employee(Long id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.entity;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
@XmlRootElement
|
||||||
|
@Entity
|
||||||
|
public class Fruit {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private long id;
|
||||||
|
private String name;
|
||||||
|
private String color;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getColor() {
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor(String color) {
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.baeldung.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import com.baeldung.entity.Employee;
|
||||||
|
|
||||||
|
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
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;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import com.baeldung.entity.Fruit;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface FruitRepository extends JpaRepository<Fruit, Long> {
|
||||||
|
|
||||||
|
Long deleteByName(String name);
|
||||||
|
|
||||||
|
List<Fruit> deleteByColor(String color);
|
||||||
|
|
||||||
|
Long removeByName(String name);
|
||||||
|
|
||||||
|
List<Fruit> removeByColor(String color);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Query("delete from Fruit f where f.name=:name or f.color=:color")
|
||||||
|
int deleteFruits(@Param("name") String name, @Param("color") String color);
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.schemageneration;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class AccountApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(AccountApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.schemageneration;
|
||||||
|
|
||||||
|
import com.baeldung.schemageneration.model.Account;
|
||||||
|
import com.baeldung.schemageneration.model.AccountSetting;
|
||||||
|
import org.hibernate.boot.Metadata;
|
||||||
|
import org.hibernate.boot.MetadataSources;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
|
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||||
|
import org.hibernate.tool.schema.TargetType;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HibernateUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates database create commands for the specified entities using Hibernate native API, SchemaExport.
|
||||||
|
* Creation commands are exported into the create.sql file.
|
||||||
|
*/
|
||||||
|
public static void generateSchema() {
|
||||||
|
Map<String, String> settings = new HashMap<>();
|
||||||
|
settings.put(Environment.URL, "jdbc:h2:mem:schema");
|
||||||
|
|
||||||
|
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(settings).build();
|
||||||
|
|
||||||
|
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
|
||||||
|
metadataSources.addAnnotatedClass(Account.class);
|
||||||
|
metadataSources.addAnnotatedClass(AccountSetting.class);
|
||||||
|
Metadata metadata = metadataSources.buildMetadata();
|
||||||
|
|
||||||
|
SchemaExport schemaExport = new SchemaExport();
|
||||||
|
schemaExport.setFormat(true);
|
||||||
|
schemaExport.setOutputFile("create.sql");
|
||||||
|
schemaExport.createOnly(EnumSet.of(TargetType.SCRIPT), metadata);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.baeldung.schemageneration.model;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "accounts")
|
||||||
|
public class Account {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false, length = 100)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column(name = "email_address")
|
||||||
|
private String emailAddress;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "account", cascade = CascadeType.ALL)
|
||||||
|
private List<AccountSetting> accountSettings = new ArrayList<>();
|
||||||
|
|
||||||
|
public Account() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account(String name, String emailAddress) {
|
||||||
|
this.name = name;
|
||||||
|
this.emailAddress = emailAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmailAddress() {
|
||||||
|
return emailAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailAddress(String emailAddress) {
|
||||||
|
this.emailAddress = emailAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AccountSetting> getAccountSettings() {
|
||||||
|
return accountSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccountSettings(List<AccountSetting> accountSettings) {
|
||||||
|
this.accountSettings = accountSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAccountSetting(AccountSetting setting) {
|
||||||
|
this.accountSettings.add(setting);
|
||||||
|
setting.setAccount(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.baeldung.schemageneration.model;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "account_settings")
|
||||||
|
public class AccountSetting {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "name", nullable = false)
|
||||||
|
private String settingName;
|
||||||
|
|
||||||
|
@Column(name = "value", nullable = false)
|
||||||
|
private String settingValue;
|
||||||
|
|
||||||
|
@ManyToOne()
|
||||||
|
@JoinColumn(name ="account_id", nullable = false)
|
||||||
|
private Account account;
|
||||||
|
|
||||||
|
public AccountSetting() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountSetting(String settingName, String settingValue) {
|
||||||
|
this.settingName = settingName;
|
||||||
|
this.settingValue = settingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSettingName() {
|
||||||
|
return settingName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSettingName(String settingName) {
|
||||||
|
this.settingName = settingName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSettingValue() {
|
||||||
|
return settingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSettingValue(String settingValue) {
|
||||||
|
this.settingValue = settingValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccount(Account account) {
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.schemageneration.repository;
|
||||||
|
|
||||||
|
import com.baeldung.schemageneration.model.Account;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
|
public interface AccountRepository extends CrudRepository<Account, Long> {
|
||||||
|
Account findByName(String name);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package com.baeldung.schemageneration.repository;
|
||||||
|
|
||||||
|
import com.baeldung.schemageneration.model.AccountSetting;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
|
||||||
|
public interface AccountSettingRepository extends CrudRepository<AccountSetting, Long> {
|
||||||
|
AccountSetting findByAccountId(Long accountId);
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
spring.main.allow-bean-definition-overriding=true
|
||||||
|
|
||||||
|
spring.jpa.properties.hibernate.jdbc.batch_size=4
|
||||||
|
spring.jpa.properties.hibernate.order_inserts=true
|
||||||
|
spring.jpa.properties.hibernate.order_updates=true
|
||||||
|
spring.jpa.properties.hibernate.generate_statistics=true
|
||||||
|
|
||||||
|
# JPA-Schema-Generation
|
||||||
|
# Use below configuration to generate database schema create commands based on the entity models
|
||||||
|
# and export them into the create.sql file
|
||||||
|
#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
|
||||||
|
#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
|
||||||
|
#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-source=metadata
|
||||||
|
#spring.jpa.properties.hibernate.format_sql=true
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||||
|
</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import com.baeldung.boot.Application;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = Application.class)
|
||||||
|
public class SpringContextTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import com.baeldung.boot.Application;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@DataJpaTest
|
||||||
|
@ContextConfiguration(classes = Application.class)
|
||||||
|
public class SpringJpaContextIntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.batchinserts;
|
||||||
|
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
|
||||||
|
import com.baeldung.boot.Application;
|
||||||
|
import com.baeldung.boot.daos.CustomerRepository;
|
||||||
|
import com.baeldung.boot.web.controllers.CustomerController;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes=Application.class)
|
||||||
|
@AutoConfigureMockMvc
|
||||||
|
public class BatchInsertIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CustomerRepository customerRepository;
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mockMvc = MockMvcBuilders.standaloneSetup( new CustomerController(customerRepository))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInsertingCustomers_thenCustomersAreCreated() throws Exception {
|
||||||
|
this.mockMvc.perform(post("/customers"))
|
||||||
|
.andExpect(status().isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.baeldung.batchinserts;
|
||||||
|
|
||||||
|
import static com.baeldung.batchinserts.TestObjectHelper.createSchool;
|
||||||
|
import static com.baeldung.batchinserts.TestObjectHelper.createStudent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.baeldung.batchinserts.model.School;
|
||||||
|
import com.baeldung.batchinserts.model.Student;
|
||||||
|
import com.baeldung.boot.Application;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = Application.class)
|
||||||
|
@Transactional
|
||||||
|
@ActiveProfiles("batchinserts")
|
||||||
|
public class JpaBatchInsertsIntegrationTest {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
private static final int BATCH_SIZE = 5;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
public void whenInsertingSingleTypeOfEntity_thenCreatesSingleBatch() {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
School school = createSchool(i);
|
||||||
|
entityManager.persist(school);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
public void whenFlushingAfterBatch_ThenClearsMemory() {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
if (i > 0 && i % BATCH_SIZE == 0) {
|
||||||
|
entityManager.flush();
|
||||||
|
entityManager.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
School school = createSchool(i);
|
||||||
|
entityManager.persist(school);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
public void whenThereAreMultipleEntities_ThenCreatesNewBatch() {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
if (i > 0 && i % BATCH_SIZE == 0) {
|
||||||
|
entityManager.flush();
|
||||||
|
entityManager.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
School school = createSchool(i);
|
||||||
|
entityManager.persist(school);
|
||||||
|
Student firstStudent = createStudent(school);
|
||||||
|
Student secondStudent = createStudent(school);
|
||||||
|
entityManager.persist(firstStudent);
|
||||||
|
entityManager.persist(secondStudent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
public void whenUpdatingEntities_thenCreatesBatch() {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
School school = createSchool(i);
|
||||||
|
entityManager.persist(school);
|
||||||
|
}
|
||||||
|
|
||||||
|
entityManager.flush();
|
||||||
|
|
||||||
|
TypedQuery<School> schoolQuery = entityManager.createQuery("SELECT s from School s", School.class);
|
||||||
|
List<School> allSchools = schoolQuery.getResultList();
|
||||||
|
|
||||||
|
for (School school : allSchools) {
|
||||||
|
school.setName("Updated_" + school.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
entityManager.flush();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.baeldung.batchinserts;
|
||||||
|
|
||||||
|
import static com.baeldung.batchinserts.TestObjectHelper.createSchool;
|
||||||
|
|
||||||
|
import com.baeldung.batchinserts.model.School;
|
||||||
|
import com.baeldung.boot.Application;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceContext;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = Application.class)
|
||||||
|
@Transactional
|
||||||
|
@ActiveProfiles("batchinserts")
|
||||||
|
@TestPropertySource(properties = "spring.jpa.properties.hibernate.jdbc.batch_size=-1")
|
||||||
|
public class JpaNoBatchInsertsIntegrationTest {
|
||||||
|
|
||||||
|
@PersistenceContext
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNotConfigured_ThenSendsInsertsSeparately() {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
School school = createSchool(i);
|
||||||
|
entityManager.persist(school);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
entityManager.flush();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.batchinserts;
|
||||||
|
|
||||||
|
import com.baeldung.batchinserts.model.School;
|
||||||
|
import com.baeldung.batchinserts.model.Student;
|
||||||
|
|
||||||
|
public class TestObjectHelper {
|
||||||
|
|
||||||
|
public static School createSchool(int nameIdentifier) {
|
||||||
|
School school = new School();
|
||||||
|
school.setName("School" + (nameIdentifier + 1));
|
||||||
|
return school;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Student createStudent(School school) {
|
||||||
|
Student student = new Student();
|
||||||
|
student.setName("Student-" + school.getName());
|
||||||
|
student.setSchool(school);
|
||||||
|
return student;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.baeldung.boot.daos;
|
||||||
|
|
||||||
|
import com.baeldung.boot.daos.impl.PersonInsertRepository;
|
||||||
|
import com.baeldung.boot.domain.Person;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import javax.persistence.EntityExistsException;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.PersistenceException;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@DataJpaTest
|
||||||
|
@Import(PersonInsertRepository.class)
|
||||||
|
public class PersonInsertRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
private static final Long ID = 1L;
|
||||||
|
private static final String FIRST_NAME = "firstname";
|
||||||
|
private static final String LAST_NAME = "lastname";
|
||||||
|
private static final Person PERSON = new Person(ID, FIRST_NAME, LAST_NAME);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PersonInsertRepository personInsertRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EntityManager entityManager;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonEntity_whenInsertWithNativeQuery_ThenPersonIsPersisted() {
|
||||||
|
insertWithQuery();
|
||||||
|
|
||||||
|
assertPersonPersisted();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonEntity_whenInsertedTwiceWithNativeQuery_thenPersistenceExceptionExceptionIsThrown() {
|
||||||
|
assertThatExceptionOfType(PersistenceException.class).isThrownBy(() -> {
|
||||||
|
insertWithQuery();
|
||||||
|
insertWithQuery();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonEntity_whenInsertWithEntityManager_thenPersonIsPersisted() {
|
||||||
|
insertPersonWithEntityManager();
|
||||||
|
|
||||||
|
assertPersonPersisted();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonEntity_whenInsertedTwiceWithEntityManager_thenEntityExistsExceptionIsThrown() {
|
||||||
|
assertThatExceptionOfType(EntityExistsException.class).isThrownBy(() -> {
|
||||||
|
insertPersonWithEntityManager();
|
||||||
|
insertPersonWithEntityManager();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertWithQuery() {
|
||||||
|
personInsertRepository.insertWithQuery(PERSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertPersonWithEntityManager() {
|
||||||
|
personInsertRepository.insertWithEntityManager(new Person(ID, FIRST_NAME, LAST_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertPersonPersisted() {
|
||||||
|
Person person = entityManager.find(Person.class, ID);
|
||||||
|
|
||||||
|
assertThat(person).isNotNull();
|
||||||
|
assertThat(person.getId()).isEqualTo(PERSON.getId());
|
||||||
|
assertThat(person.getFirstName()).isEqualTo(PERSON.getFirstName());
|
||||||
|
assertThat(person.getLastName()).isEqualTo(PERSON.getLastName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.baeldung.datajpadelete;
|
||||||
|
|
||||||
|
import com.baeldung.Application;
|
||||||
|
import com.baeldung.datajpadelete.entity.Book;
|
||||||
|
import com.baeldung.datajpadelete.repository.BookRepository;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = {Application.class})
|
||||||
|
public class DeleteFromRepositoryUnitTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BookRepository repository;
|
||||||
|
|
||||||
|
Book book1;
|
||||||
|
Book book2;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
book1 = new Book("The Hobbit");
|
||||||
|
book2 = new Book("All Quiet on the Western Front");
|
||||||
|
|
||||||
|
repository.saveAll(Arrays.asList(book1, book2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void teardown() {
|
||||||
|
repository.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDeleteByIdFromRepository_thenDeletingShouldBeSuccessful() {
|
||||||
|
repository.deleteById(book1.getId());
|
||||||
|
|
||||||
|
assertThat(repository.count()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty() {
|
||||||
|
repository.deleteAll();
|
||||||
|
|
||||||
|
assertThat(repository.count()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Transactional
|
||||||
|
public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful() {
|
||||||
|
long deletedRecords = repository.deleteByTitle("The Hobbit");
|
||||||
|
|
||||||
|
assertThat(deletedRecords).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Transactional
|
||||||
|
public void whenDeleteFromCustomQuery_thenDeletingShouldBeSuccessful() {
|
||||||
|
repository.deleteBooks("The Hobbit");
|
||||||
|
|
||||||
|
assertThat(repository.count()).isEqualTo(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.baeldung.datajpadelete;
|
||||||
|
|
||||||
|
import com.baeldung.Application;
|
||||||
|
import com.baeldung.datajpadelete.entity.Book;
|
||||||
|
import com.baeldung.datajpadelete.entity.Category;
|
||||||
|
import com.baeldung.datajpadelete.repository.BookRepository;
|
||||||
|
import com.baeldung.datajpadelete.repository.CategoryRepository;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = {Application.class})
|
||||||
|
public class DeleteInRelationshipsUnitTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BookRepository bookRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CategoryRepository categoryRepository;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
Book book1 = new Book("The Hobbit");
|
||||||
|
Category category1 = new Category("Cat1", book1);
|
||||||
|
categoryRepository.save(category1);
|
||||||
|
|
||||||
|
Book book2 = new Book("All Quiet on the Western Front");
|
||||||
|
Category category2 = new Category("Cat2", book2);
|
||||||
|
categoryRepository.save(category2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void teardown() {
|
||||||
|
bookRepository.deleteAll();
|
||||||
|
categoryRepository.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDeletingCategories_thenBooksShouldAlsoBeDeleted() {
|
||||||
|
categoryRepository.deleteAll();
|
||||||
|
|
||||||
|
assertThat(bookRepository.count()).isEqualTo(0);
|
||||||
|
assertThat(categoryRepository.count()).isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDeletingBooks_thenCategoriesShouldAlsoBeDeleted() {
|
||||||
|
bookRepository.deleteAll();
|
||||||
|
|
||||||
|
assertThat(bookRepository.count()).isEqualTo(0);
|
||||||
|
assertThat(categoryRepository.count()).isEqualTo(2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.baeldung.repository;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import com.baeldung.boot.Application;
|
||||||
|
import com.baeldung.entity.Employee;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = Application.class)
|
||||||
|
public class EmployeeRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
private static final Employee EMPLOYEE1 = new Employee(1L, "John");
|
||||||
|
private static final Employee EMPLOYEE2 = new Employee(2L, "Alice");
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EmployeeRepository employeeRepository;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmployeeEntity_whenInsertWithSave_ThenEmployeeIsPersisted() {
|
||||||
|
employeeRepository.save(EMPLOYEE1);
|
||||||
|
assertEmployeePersisted(EMPLOYEE1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmployeeEntity_whenInsertWithSaveAndFlush_ThenEmployeeIsPersisted() {
|
||||||
|
employeeRepository.saveAndFlush(EMPLOYEE2);
|
||||||
|
assertEmployeePersisted(EMPLOYEE2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertEmployeePersisted(Employee input) {
|
||||||
|
Employee employee = employeeRepository.getOne(input.getId());
|
||||||
|
assertThat(employee).isNotNull();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.baeldung.repository;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.jdbc.Sql;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import com.baeldung.entity.Fruit;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
class FruitRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FruitRepository fruitRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
@Sql(scripts = { "/test-fruit-data.sql" })
|
||||||
|
public void givenFruits_WhenDeletedByColor_ThenDeletedFruitsShouldReturn() {
|
||||||
|
|
||||||
|
List<Fruit> fruits = fruitRepository.deleteByColor("green");
|
||||||
|
|
||||||
|
assertEquals("number of fruits are not matching", 2, fruits.size());
|
||||||
|
fruits.forEach(fruit -> assertEquals("Its not a green fruit", "green", fruit.getColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
@Sql(scripts = { "/test-fruit-data.sql" })
|
||||||
|
public void givenFruits_WhenDeletedByName_ThenDeletedFruitCountShouldReturn() {
|
||||||
|
|
||||||
|
Long deletedFruitCount = fruitRepository.deleteByName("apple");
|
||||||
|
|
||||||
|
assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
@Sql(scripts = { "/test-fruit-data.sql" })
|
||||||
|
public void givenFruits_WhenRemovedByColor_ThenDeletedFruitsShouldReturn() {
|
||||||
|
|
||||||
|
List<Fruit> fruits = fruitRepository.removeByColor("green");
|
||||||
|
|
||||||
|
assertEquals("number of fruits are not matching", 2, fruits.size());
|
||||||
|
fruits.forEach(fruit -> assertEquals("Its not a green fruit", "green", fruit.getColor()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
@Sql(scripts = { "/test-fruit-data.sql" })
|
||||||
|
public void givenFruits_WhenRemovedByName_ThenDeletedFruitCountShouldReturn() {
|
||||||
|
|
||||||
|
Long deletedFruitCount = fruitRepository.removeByName("apple");
|
||||||
|
|
||||||
|
assertEquals("deleted fruit count is not matching", 1, deletedFruitCount.intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
@Test
|
||||||
|
@Sql(scripts = { "/test-fruit-data.sql" })
|
||||||
|
public void givenFruits_WhenDeletedByColorOrName_ThenDeletedFruitsShouldReturn() {
|
||||||
|
|
||||||
|
int deletedCount = fruitRepository.deleteFruits("apple", "green");
|
||||||
|
|
||||||
|
assertEquals("number of fruits are not matching", 3, deletedCount);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.baeldung.schemageneration;
|
||||||
|
|
||||||
|
import com.baeldung.schemageneration.model.Account;
|
||||||
|
import com.baeldung.schemageneration.model.AccountSetting;
|
||||||
|
import com.baeldung.schemageneration.repository.AccountRepository;
|
||||||
|
import com.baeldung.schemageneration.repository.AccountSettingRepository;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(classes = AccountApplication.class)
|
||||||
|
public class AccountRepositoryIntegrationTest {
|
||||||
|
|
||||||
|
private static final String USER_NAME = "Eduard";
|
||||||
|
private static final String USER_EMAIL_ADDRESS = "eduard@gmx.com";
|
||||||
|
private static final String ACCOUNT_SETTING_NAME = "Timezone";
|
||||||
|
private static final String ACCOUNT_SETTING_VALUE = "UTC+02";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AccountRepository accountRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AccountSettingRepository accountSettingRepository;
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
accountRepository.deleteAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNewAccount_whenSave_thenSuccess() {
|
||||||
|
Account account = new Account(USER_NAME, USER_EMAIL_ADDRESS);
|
||||||
|
accountRepository.save(account);
|
||||||
|
|
||||||
|
assertEquals(1, accountRepository.count());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSavedAccount_whenFindByName_thenFound() {
|
||||||
|
Account account = new Account(USER_NAME, USER_EMAIL_ADDRESS);
|
||||||
|
accountRepository.save(account);
|
||||||
|
|
||||||
|
Account accountFound = accountRepository.findByName(USER_NAME);
|
||||||
|
|
||||||
|
assertNotNull(accountFound);
|
||||||
|
assertEquals(USER_NAME, accountFound.getName());
|
||||||
|
assertEquals(USER_EMAIL_ADDRESS, accountFound.getEmailAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSavedAccount_whenAccountSettingIsAdded_thenPersisted() {
|
||||||
|
Account account = new Account(USER_NAME, USER_EMAIL_ADDRESS);
|
||||||
|
account.addAccountSetting(new AccountSetting(ACCOUNT_SETTING_NAME, ACCOUNT_SETTING_VALUE));
|
||||||
|
accountRepository.save(account);
|
||||||
|
|
||||||
|
Account accountFound = accountRepository.findByName(USER_NAME);
|
||||||
|
assertNotNull(accountFound);
|
||||||
|
AccountSetting accountSetting = accountSettingRepository.findByAccountId(accountFound.getId());
|
||||||
|
|
||||||
|
assertNotNull(accountSetting);
|
||||||
|
assertEquals(ACCOUNT_SETTING_NAME, accountSetting.getSettingName());
|
||||||
|
assertEquals(ACCOUNT_SETTING_VALUE, accountSetting.getSettingValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
spring.jpa.show-sql=false
|
||||||
|
|
||||||
|
spring.jpa.properties.hibernate.jdbc.batch_size=5
|
||||||
|
spring.jpa.properties.hibernate.order_inserts=true
|
||||||
|
spring.jpa.properties.hibernate.order_updates=true
|
||||||
|
spring.jpa.properties.hibernate.batch_versioned_data=true
|
|
@ -0,0 +1,2 @@
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
spring.datasource.url=jdbc:h2:mem:jpa3
|
|
@ -0,0 +1,6 @@
|
||||||
|
truncate table fruit;
|
||||||
|
|
||||||
|
insert into fruit(id,name,color) values (1,'apple','red');
|
||||||
|
insert into fruit(id,name,color) values (2,'custard apple','green');
|
||||||
|
insert into fruit(id,name,color) values (3,'mango','yellow');
|
||||||
|
insert into fruit(id,name,color) values (4,'guava','green');
|
Loading…
Reference in New Issue