diff --git a/java/23ai-springboot3-jdbc/README.md b/java/23ai-springboot3-jdbc/README.md
new file mode 100644
index 00000000..71d3519f
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/README.md
@@ -0,0 +1 @@
+[Spring Data JDBC with the Oracle Database for Java Developers - Getting Started Guide](https://medium.com/oracledevs/spring-data-jdbc-with-the-oracle-database-23c-for-java-developers-getting-started-guide-1c4640fc8d27)
diff --git a/java/23ai-springboot3-jdbc/pom.xml b/java/23ai-springboot3-jdbc/pom.xml
new file mode 100644
index 00000000..1b6f5f55
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/pom.xml
@@ -0,0 +1,71 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.2.0
+
+
+ com.oracle.dev.springdata.jdbc
+ 23ai-springboot3-jdbc
+ 0.0.1-SNAPSHOT
+ 23ai-springboot3-jdbc
+
+ 21
+
+
+
+ com.oracle.database.jdbc
+ ojdbc11
+ 23.6.0.24.10
+
+
+ com.oracle.database.jdbc
+ ucp17
+ 23.6.0.24.10
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ maven-compiler-plugin
+
+
+
+
+
+
+
+
+
diff --git a/java/23ai-springboot3-jdbc/script/EMPLOYEE.SQL b/java/23ai-springboot3-jdbc/script/EMPLOYEE.SQL
new file mode 100644
index 00000000..edd9ff31
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/script/EMPLOYEE.SQL
@@ -0,0 +1,28 @@
+CREATE USER ORACLE_23C_USER IDENTIFIED BY ;
+GRANT DB_DEVELOPER_ROLE TO ORACLE_23C_USER;
+GRANT CREATE SESSION TO ORACLE_23C_USER;
+GRANT UNLIMITED TABLESPACE TO ORACLE_23C_USER;
+
+CREATE TABLE Employee
+ (id NUMBER(10) CONSTRAINT pk_employee PRIMARY KEY,
+ name VARCHAR2(20),
+ job VARCHAR2(20),
+ salary NUMBER(10),
+ commission NUMBER(10));
+
+INSERT INTO Employee VALUES(7369,'JOHN','CLERK',7902,NULL);
+INSERT INTO Employee VALUES(7499,'PETER','SALESMAN',7698,300);
+INSERT INTO Employee VALUES(7521,'JEFF','SALESMAN',7698,500);
+INSERT INTO Employee VALUES(7566,'MARK','MANAGER',7839,NULL);
+INSERT INTO Employee VALUES(7654,'MARTIN','SALESMAN',7698,1400);
+INSERT INTO Employee VALUES(7698,'ADAM','MANAGER',7839,NULL);
+INSERT INTO Employee VALUES(7782,'CLARK','MANAGER',7839,NULL);
+INSERT INTO Employee VALUES(7788,'SCOTT','ANALYST',7566,NULL);
+INSERT INTO Employee VALUES(7839,'KING','PRESIDENT',NULL);
+INSERT INTO Employee VALUES(7844,'TURNER','SALESMAN',0);
+INSERT INTO Employee VALUES(7876,'ADAMS','CLERK',7788,NULL);
+INSERT INTO Employee VALUES(7900,'JAMES','CLERK',7698,NULL);
+INSERT INTO Employee VALUES(7902,'FORD','ANALYST',7566,NULL);
+INSERT INTO Employee VALUES(7934,'MILLER','CLERK',7782,NULL);
+
+COMMIT;
\ No newline at end of file
diff --git a/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/Employee.java b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/Employee.java
new file mode 100644
index 00000000..eca7c9fa
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/Employee.java
@@ -0,0 +1,115 @@
+/*
+ Copyright (c) 2024, Oracle and/or its affiliates.
+
+ This software is dual-licensed to you under the Universal Permissive License
+ (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
+ 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
+ either license.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package com.oracle.dev.springdata.jdbc;
+
+import java.util.Objects;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.relational.core.mapping.Table;
+
+@Table
+public class Employee {
+
+ private @Id Long id;
+ private String name;
+ private String job;
+ private Integer salary;
+ private Integer commission;
+
+ public Employee() {
+ }
+
+ public Employee(Long id, String name, String job, Integer salary,
+ Integer commission) {
+ this.id = id;
+ this.name = name;
+ this.job = job;
+ this.salary = salary;
+ this.commission = commission;
+ }
+
+ 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 getJob() {
+ return job;
+ }
+
+ public void setJob(String job) {
+ this.job = job;
+ }
+
+ public Integer getSalary() {
+ return salary;
+ }
+
+ public void setSalary(Integer salary) {
+ this.salary = salary;
+ }
+
+ public Integer getCommission() {
+ return commission;
+ }
+
+ public void setCommission(Integer commission) {
+ this.commission = commission;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(commission, id, job, name, salary);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Employee other = (Employee) obj;
+ return Objects.equals(commission, other.commission)
+ && Objects.equals(id, other.id) && Objects.equals(job, other.job)
+ && Objects.equals(name, other.name)
+ && Objects.equals(salary, other.salary);
+ }
+
+ public String toString() {
+ return String.format("%20s %20s %20s %20s %20s", id, name, job, salary,
+ commission);
+
+ }
+}
diff --git a/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeApplication.java b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeApplication.java
new file mode 100644
index 00000000..a3f05d61
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeApplication.java
@@ -0,0 +1,34 @@
+/*
+ Copyright (c) 2024, Oracle and/or its affiliates.
+
+ This software is dual-licensed to you under the Universal Permissive License
+ (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
+ 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
+ either license.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package com.oracle.dev.springdata.jdbc;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class EmployeeApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(EmployeeApplication.class, args);
+ }
+
+}
diff --git a/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeController.java b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeController.java
new file mode 100644
index 00000000..a3f62a93
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeController.java
@@ -0,0 +1,76 @@
+/*
+ Copyright (c) 2024, Oracle and/or its affiliates.
+
+ This software is dual-licensed to you under the Universal Permissive License
+ (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
+ 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
+ either license.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package com.oracle.dev.springdata.jdbc;
+
+import org.springframework.web.bind.annotation.DeleteMapping;
+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.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+class EmployeeController {
+
+ private final EmployeeRepository repository;
+
+ EmployeeController(EmployeeRepository repository) {
+ this.repository = repository;
+ }
+
+ @GetMapping("/employees")
+ Iterable all() {
+ return repository.findAll();
+ }
+
+ @PostMapping("/employees")
+ Employee newEmployee(@RequestBody Employee newEmployee) {
+ return repository.save(newEmployee);
+ }
+
+ @GetMapping("/employees/{id}")
+ Employee one(@PathVariable Long id) {
+
+ return repository.findById(id)
+ .orElseThrow(() -> new EmployeeNotFoundException(id));
+ }
+
+ @PutMapping("/employees/{id}")
+ Employee replaceEmployee(@RequestBody Employee newEmployee,
+ @PathVariable Long id) {
+
+ return repository.findById(id).map(employee -> {
+ employee.setName(newEmployee.getName());
+ employee.setJob(newEmployee.getJob());
+ return repository.save(employee);
+ }).orElseGet(() -> {
+ newEmployee.setId(id);
+ return repository.save(newEmployee);
+ });
+ }
+
+ @DeleteMapping("/employees/{id}")
+ void deleteEmployee(@PathVariable Long id) {
+ repository.deleteById(id);
+ }
+}
\ No newline at end of file
diff --git a/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeNotFoundAdvice.java b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeNotFoundAdvice.java
new file mode 100644
index 00000000..28b5090b
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeNotFoundAdvice.java
@@ -0,0 +1,39 @@
+/*
+ Copyright (c) 2024, Oracle and/or its affiliates.
+
+ This software is dual-licensed to you under the Universal Permissive License
+ (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
+ 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
+ either license.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package com.oracle.dev.springdata.jdbc;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ControllerAdvice
+class EmployeeNotFoundAdvice {
+
+ @ResponseBody
+ @ExceptionHandler(EmployeeNotFoundException.class)
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ String employeeNotFoundHandler(EmployeeNotFoundException ex) {
+ return ex.getMessage();
+ }
+}
\ No newline at end of file
diff --git a/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeNotFoundException.java b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeNotFoundException.java
new file mode 100644
index 00000000..25c64567
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeNotFoundException.java
@@ -0,0 +1,31 @@
+/*
+ Copyright (c) 2024, Oracle and/or its affiliates.
+
+ This software is dual-licensed to you under the Universal Permissive License
+ (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
+ 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
+ either license.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package com.oracle.dev.springdata.jdbc;
+
+class EmployeeNotFoundException extends RuntimeException {
+
+ private static final long serialVersionUID = 7768215094663842819L;
+
+ EmployeeNotFoundException(Long id) {
+ super("Could not find employee " + id);
+ }
+}
\ No newline at end of file
diff --git a/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeRepository.java b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeRepository.java
new file mode 100644
index 00000000..fce67dc3
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/java/com/oracle/dev/springdata/jdbc/EmployeeRepository.java
@@ -0,0 +1,39 @@
+/*
+ Copyright (c) 2024, Oracle and/or its affiliates.
+
+ This software is dual-licensed to you under the Universal Permissive License
+ (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
+ 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
+ either license.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package com.oracle.dev.springdata.jdbc;
+
+import java.util.List;
+
+import org.springframework.data.jdbc.repository.query.Modifying;
+import org.springframework.data.jdbc.repository.query.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+
+interface EmployeeRepository extends CrudRepository {
+
+ List findByName(String name);
+
+ @Modifying
+ @Query("UPDATE employee SET name = :name WHERE id = :id")
+ boolean updateByName(@Param("id") Long id, @Param("name") String name);
+
+}
\ No newline at end of file
diff --git a/java/23ai-springboot3-jdbc/src/main/resources/application.properties b/java/23ai-springboot3-jdbc/src/main/resources/application.properties
new file mode 100644
index 00000000..41d447b2
--- /dev/null
+++ b/java/23ai-springboot3-jdbc/src/main/resources/application.properties
@@ -0,0 +1,15 @@
+# https://www.oracle.com/database/technologies/getting-started-using-jdbc.html
+
+# Oracle Database 23ai Free - DB instance details
+# JDBC URL EXAMPLE = jdbc:oracle:thin:@:/
+spring.datasource.url=
+spring.datasource.username=
+spring.datasource.password=
+
+# Properties for UCP - Universal Connection Pool (UCP). Spring Boot 2.4.0 or above is required
+spring.datasource.type=oracle.ucp.jdbc.PoolDataSource
+spring.datasource.oracleucp.connection-pool-name=connectionPoolName1
+spring.datasource.oracleucp.initial-pool-size=1
+spring.datasource.oracleucp.min-pool-size=1
+spring.datasource.oracleucp.max-pool-size=2
+spring.datasource.oracleucp.connection-factory-class-name=oracle.jdbc.pool.OracleDataSource