diff --git a/persistence-modules/spring-boot-persistence-2/README.md b/persistence-modules/spring-boot-persistence-2/README.md
index 5d171fb2ca..a74bf7ff02 100644
--- a/persistence-modules/spring-boot-persistence-2/README.md
+++ b/persistence-modules/spring-boot-persistence-2/README.md
@@ -1,3 +1,4 @@
### Relevant Articles:
- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi)
+- [Oracle Connection Pooling With Spring](https://www.baeldung.com/oracle-connection-pooling-with-spring)
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-2/pom.xml b/persistence-modules/spring-boot-persistence-2/pom.xml
index 048dd45c7f..8f76bce1b3 100644
--- a/persistence-modules/spring-boot-persistence-2/pom.xml
+++ b/persistence-modules/spring-boot-persistence-2/pom.xml
@@ -41,10 +41,20 @@
-
- org.springframework.boot
- spring-boot-starter-jdbc
-
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ net.bytebuddy
+ byte-buddy
+
org.jdbi
@@ -82,6 +92,47 @@
spring-boot-starter-test
test
+
+
+ com.oracle
+ ojdbc8
+ 12.2.0.1
+ system
+ ${basedir}/lib/ojdbc8.jar
+
+
+
+ com.oracle
+ ucp
+ 12.2.0.1
+ system
+ ${basedir}/lib/ucp.jar
+
+
+
+ com.oracle
+ ons
+ 12.2.0.1
+ system
+ ${basedir}/lib/ons.jar
+
+
+
+ com.mchange
+ c3p0
+ ${c3p0.version}
+
+
+
+ org.apache.commons
+ commons-dbcp2
+
+
+
+ org.apache.tomcat
+ tomcat-jdbc
+
+
@@ -96,6 +147,7 @@
3.9.1
2.1.8.RELEASE
+ 0.9.5.2
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java
new file mode 100644
index 0000000000..fa7f884112
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplication.java
@@ -0,0 +1,29 @@
+package com.baeldung.spring.oracle.pooling;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import lombok.extern.slf4j.Slf4j;
+
+@SpringBootApplication
+@Slf4j
+public class SpringOraclePoolingApplication implements CommandLineRunner{
+
+ @Autowired
+ private DataSource dataSource;
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringOraclePoolingApplication.class, args);
+ }
+
+ @Override
+ public void run(String... args) throws Exception {
+ log.info("Connection Polling datasource : "+ dataSource);
+
+ }
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java
new file mode 100644
index 0000000000..f357924807
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/C3P0Configuration.java
@@ -0,0 +1,27 @@
+package com.baeldung.spring.oracle.pooling.configuration;
+
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+@Configuration
+@Profile("c3p0")
+public class C3P0Configuration {
+
+ @Bean
+ public DataSource dataSource() throws SQLException {
+ ComboPooledDataSource dataSource = new ComboPooledDataSource();
+ dataSource.setUser("books");
+ dataSource.setPassword("books");
+ dataSource.setJdbcUrl("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1");
+ dataSource.setMinPoolSize(5);
+ dataSource.setMaxPoolSize(10);
+ return dataSource;
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java
new file mode 100644
index 0000000000..327374cb54
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleConfiguration.java
@@ -0,0 +1,27 @@
+package com.baeldung.spring.oracle.pooling.configuration;
+
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import oracle.jdbc.pool.OracleDataSource;
+
+@Configuration
+@Profile("oracle")
+public class OracleConfiguration {
+
+ @Bean
+ public DataSource dataSource() throws SQLException {
+ OracleDataSource dataSource = new OracleDataSource();
+ dataSource.setUser("books");
+ dataSource.setPassword("books");
+ dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1");
+ dataSource.setFastConnectionFailoverEnabled(true);
+ dataSource.setImplicitCachingEnabled(true);
+ return dataSource;
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java
new file mode 100644
index 0000000000..67b4b40712
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/configuration/OracleUCPConfiguration.java
@@ -0,0 +1,30 @@
+package com.baeldung.spring.oracle.pooling.configuration;
+
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+import oracle.ucp.jdbc.PoolDataSource;
+import oracle.ucp.jdbc.PoolDataSourceFactory;
+
+@Configuration
+@Profile("oracle-ucp")
+public class OracleUCPConfiguration {
+
+ @Bean
+ public DataSource dataSource() throws SQLException {
+ PoolDataSource dataSource = PoolDataSourceFactory.getPoolDataSource();
+ dataSource.setUser("books");
+ dataSource.setPassword("books");
+ dataSource.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
+ dataSource.setURL("jdbc:oracle:thin:@//localhost:11521/ORCLPDB1");
+ dataSource.setFastConnectionFailoverEnabled(true);
+ dataSource.setInitialPoolSize(5);
+ dataSource.setMaxPoolSize(10);
+ return dataSource;
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java
new file mode 100644
index 0000000000..49b998bfb9
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/controller/BookstoreController.java
@@ -0,0 +1,45 @@
+package com.baeldung.spring.oracle.pooling.controller;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.spring.oracle.pooling.entity.Book;
+import com.baeldung.spring.oracle.pooling.exception.BookstoreException;
+import com.baeldung.spring.oracle.pooling.repository.BookRepository;
+
+@RestController
+@RequestMapping("/books")
+public class BookstoreController {
+
+ @Autowired
+ private BookRepository repository;
+
+ @GetMapping(value = "/hello")
+ public String sayHello() {
+ return "Hello";
+ }
+
+ @GetMapping("/all")
+ public List findAll() {
+ return repository.findAll();
+ }
+
+ @PostMapping("/create")
+ public Book newBook(@RequestBody Book newBook) {
+ return repository.save(newBook);
+ }
+
+ @GetMapping("/get/{id}")
+ public Book findOne(@PathVariable Long id) throws BookstoreException {
+ return repository.findById(id)
+ .orElseThrow(BookstoreException::new);
+ }
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java
new file mode 100644
index 0000000000..fb2c3fcf6a
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/entity/Book.java
@@ -0,0 +1,45 @@
+package com.baeldung.spring.oracle.pooling.entity;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Book {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ private String name;
+
+ public Book() {
+ }
+
+ public Book(String name) {
+ 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;
+ }
+
+ @Override
+ public String toString() {
+ return "Book [id=" + id + ", name=" + name + "]";
+ }
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java
new file mode 100644
index 0000000000..d2fb399ab3
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/exception/BookstoreException.java
@@ -0,0 +1,10 @@
+package com.baeldung.spring.oracle.pooling.exception;
+
+public class BookstoreException extends Exception{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java
new file mode 100644
index 0000000000..a50a1b24a4
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/spring/oracle/pooling/repository/BookRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.spring.oracle.pooling.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import com.baeldung.spring.oracle.pooling.entity.Book;
+
+public interface BookRepository extends JpaRepository{
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties b/persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties
new file mode 100644
index 0000000000..9a1c7fc89d
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/main/resources/application-oracle-pooling-basic.properties
@@ -0,0 +1,27 @@
+logging.level.root=INFO
+
+# OracleDB connection settings
+spring.datasource.url=jdbc:oracle:thin:@//localhost:11521/ORCLPDB1
+spring.datasource.username=books
+spring.datasource.password=books
+spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
+
+# Comment this line for standard Spring Boot default choosing algorithm
+#spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
+
+# HikariCP settings
+spring.datasource.hikari.minimumIdle=5
+spring.datasource.hikari.maximumPoolSize=20
+spring.datasource.hikari.idleTimeout=30000
+spring.datasource.hikari.maxLifetime=2000000
+spring.datasource.hikari.connectionTimeout=30000
+spring.datasource.hikari.poolName=HikariPoolBooks
+
+# Tomcat settings
+spring.datasource.tomcat.maxActive=15
+spring.datasource.tomcat.minIdle=5
+
+# JPA settings
+spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect
+spring.jpa.hibernate.use-new-id-generator-mappings=false
+spring.jpa.hibernate.ddl-auto=create
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml b/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml
index 8b13789179..4b792fd5dc 100644
--- a/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml
+++ b/persistence-modules/spring-boot-persistence-2/src/main/resources/application.yml
@@ -1 +1,9 @@
-
+# Available profiles
+# - none for no profile
+# - oracle-pooling-basic - Oracle database with HikariCP. Loads configuration from application-oracle-pooling-basic.properties
+# - oracle - Uses OracleDataSource. This profile also needs "oracle-pooling-basic"
+# - oracle-ucp - Uses PoolDataSource. This profile also needs "oracle-pooling-basic"
+# - c3p0 - Uses ComboPooledDataSource. This profile also needs "oracle-pooling-basic"
+spring:
+ profiles:
+ active: none
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java
index e4b623ee2b..93083f6c4c 100644
--- a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java
+++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/boot/jdbi/SpringBootJdbiApplicationUnitTest.java
@@ -5,10 +5,8 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
-import org.jdbi.v3.core.Jdbi;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,7 +22,7 @@ import com.baeldung.boot.jdbi.service.CarMakerService;
import lombok.extern.slf4j.Slf4j;
@RunWith(SpringRunner.class)
-@SpringBootTest
+@SpringBootTest(classes = {SpringBootJdbiApplication.class, JdbiConfiguration.class})
@Slf4j
public class SpringBootJdbiApplicationUnitTest {
diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java
new file mode 100644
index 0000000000..5a2d3f2d29
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationC3P0LiveTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.spring.oracle.pooling;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import javax.sql.DataSource;
+
+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.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {SpringOraclePoolingApplication.class})
+@ActiveProfiles({"oracle-pooling-basic", "c3p0"})
+public class SpringOraclePoolingApplicationC3P0LiveTest {
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Test
+ public void givenC3p0Configuration_thenBuildsComboPooledDataSource() {
+ assertTrue(dataSource instanceof com.mchange.v2.c3p0.ComboPooledDataSource);
+ }
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java
new file mode 100644
index 0000000000..ab8fc1e121
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationHikariCPLiveTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.spring.oracle.pooling;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import javax.sql.DataSource;
+
+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.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {SpringOraclePoolingApplication.class})
+@ActiveProfiles("oracle-pooling-basic")
+public class SpringOraclePoolingApplicationHikariCPLiveTest {
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Test
+ public void givenHikariCPConfiguration_thenBuildsHikariCP() {
+ assertTrue(dataSource instanceof com.zaxxer.hikari.HikariDataSource);
+ }
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java
new file mode 100644
index 0000000000..229375dadd
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleLiveTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.spring.oracle.pooling;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import javax.sql.DataSource;
+
+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.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {SpringOraclePoolingApplication.class})
+@ActiveProfiles({"oracle-pooling-basic", "oracle"})
+public class SpringOraclePoolingApplicationOracleLiveTest {
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Test
+ public void givenOracleConfiguration_thenBuildsOracleDataSource() {
+ assertTrue(dataSource instanceof oracle.jdbc.pool.OracleDataSource);
+ }
+
+}
diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java
new file mode 100644
index 0000000000..4fb6aa6bae
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/spring/oracle/pooling/SpringOraclePoolingApplicationOracleUCPLiveTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.spring.oracle.pooling;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import javax.sql.DataSource;
+
+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.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {SpringOraclePoolingApplication.class})
+@ActiveProfiles({"oracle-pooling-basic", "oracle-ucp"})
+public class SpringOraclePoolingApplicationOracleUCPLiveTest {
+
+ @Autowired
+ private DataSource dataSource;
+
+ @Test
+ public void givenOracleUCPConfiguration_thenBuildsOraclePoolDataSource() {
+ assertTrue(dataSource instanceof oracle.ucp.jdbc.PoolDataSource);
+ }
+
+}