From 63027fd269c46259d39e56b9ddd87380e99a5232 Mon Sep 17 00:00:00 2001 From: Gang Wu Date: Tue, 14 Apr 2020 00:43:27 -0600 Subject: [PATCH 1/5] BAEL-3961 Using a list of values in a JDBCTemplate IN clause --- .../main/java/com/baeldung/jdbc/Employee.java | 7 +++ .../java/com/baeldung/jdbc/EmployeeDAO.java | 43 ++++++++++++- .../baeldung/jdbc/EmployeeDAOUnitTest.java | 63 +++++++++++++++++-- 3 files changed, 106 insertions(+), 7 deletions(-) diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java index a43eb265c7..d5f87ca3df 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java @@ -9,6 +9,13 @@ public class Employee { private String address; + public Employee(int id, String firstName, String lastName, String address) { + setId(id); + setFirstName(firstName); + setLastName(lastName); + setAddress(address); + } + public int getId() { return id; } diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index b5bf9452ed..dec88ee1f6 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -1,21 +1,62 @@ package com.baeldung.jdbc; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + import javax.sql.DataSource; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.stereotype.Repository; @Repository public class EmployeeDAO { private JdbcTemplate jdbcTemplate; + private NamedParameterJdbcTemplate namedJdbcTemplate; public void setDataSource(DataSource dataSource) { jdbcTemplate = new JdbcTemplate(dataSource); + namedJdbcTemplate = new NamedParameterJdbcTemplate(dataSource); } public int getCountOfEmployees() { return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class); } - + public List getEmployeesFromIdListNamed(List ids) { + SqlParameterSource parameters = new MapSqlParameterSource("ids", ids); + List employees = namedJdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (:ids)", + parameters, + (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"), rs.getString("address"))); + + return employees; + } + + public List getEmployeesFromIdList(List ids) { + String inSql = String.join(",", Collections.nCopies(ids.size(), "?")); + List employees = jdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (" + inSql +")", + ids.toArray(), + (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"), rs.getString("address"))); + + return employees; + } + + public List getEmployeesFromLargeIdList(List ids) { + jdbcTemplate.execute("CREATE TEMPORARY TABLE employee_tmp (id INT NOT NULL)"); + + List employeeIds = new ArrayList<>(); + for (Integer id : ids) { + employeeIds.add(new Object[] { id }); + } + jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds); + + List employees = jdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)", + (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"), rs.getString("address"))); + + return employees; + } + } diff --git a/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java b/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java index 71e8fb4263..f21704221b 100644 --- a/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java +++ b/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java @@ -2,8 +2,12 @@ package com.baeldung.jdbc; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.ArrayList; +import java.util.List; + import javax.sql.DataSource; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -14,13 +18,24 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.test.util.ReflectionTestUtils; - @RunWith(MockitoJUnitRunner.class) public class EmployeeDAOUnitTest { @Mock JdbcTemplate jdbcTemplate; + DataSource dataSource; + + @Before + public void setup() { + dataSource = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) + .generateUniqueName(true) + .addScript("classpath:jdbc/schema.sql") + .addScript("classpath:jdbc/test-data.sql") + .build(); + + } + @Test public void whenMockJdbcTemplate_thenReturnCorrectEmployeeCount() { EmployeeDAO employeeDAO = new EmployeeDAO(); @@ -38,14 +53,50 @@ public class EmployeeDAOUnitTest { @Test public void whenInjectInMemoryDataSource_thenReturnCorrectEmployeeCount() { - DataSource dataSource = new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2) - .addScript("classpath:jdbc/schema.sql") - .addScript("classpath:jdbc/test-data.sql") - .build(); - EmployeeDAO employeeDAO = new EmployeeDAO(); employeeDAO.setDataSource(dataSource); assertEquals(4, employeeDAO.getCountOfEmployees()); } + + @Test + public void givenSmallIdList_whenGetEmployeesFromIdList_thenReturnCorrectEmployees() { + List ids = new ArrayList<>(); + ids.add(1); + ids.add(3); + ids.add(4); + EmployeeDAO employeeDAO = new EmployeeDAO(); + employeeDAO.setDataSource(dataSource); + + List employees = employeeDAO.getEmployeesFromIdList(ids); + + assertEquals(3, employees.size()); + assertEquals(1, employees.get(0).getId()); + assertEquals(3, employees.get(1).getId()); + assertEquals(4, employees.get(2).getId()); + + employees = employeeDAO.getEmployeesFromIdListNamed(ids); + + assertEquals(3, employees.size()); + assertEquals(1, employees.get(0).getId()); + assertEquals(3, employees.get(1).getId()); + assertEquals(4, employees.get(2).getId()); + } + + @Test + public void givenLargeIdList_whenGetEmployeesFromIdList_thenReturnCorrectEmployees() { + List ids = new ArrayList<>(); + ids.add(1); + ids.add(3); + ids.add(4); + EmployeeDAO employeeDAO = new EmployeeDAO(); + employeeDAO.setDataSource(dataSource); + + List employees = employeeDAO.getEmployeesFromLargeIdList(ids); + + assertEquals(3, employees.size()); + assertEquals(1, employees.get(0).getId()); + assertEquals(3, employees.get(1).getId()); + assertEquals(4, employees.get(2).getId()); + } } From 78e180f35d3a6de9a05bd122df6614075332a6ac Mon Sep 17 00:00:00 2001 From: Gang Wu Date: Tue, 14 Apr 2020 19:23:11 -0600 Subject: [PATCH 2/5] BAEL-3961 Make the program more robust by only create the table when necessary and clean all data in the temp table. --- .../src/main/java/com/baeldung/jdbc/EmployeeDAO.java | 3 ++- .../src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index dec88ee1f6..25d280ad12 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -45,7 +45,8 @@ public class EmployeeDAO { } public List getEmployeesFromLargeIdList(List ids) { - jdbcTemplate.execute("CREATE TEMPORARY TABLE employee_tmp (id INT NOT NULL)"); + jdbcTemplate.execute("CREATE TEMPORARY TABLE IF NOT EXISTS employee_tmp (id INT NOT NULL)"); + jdbcTemplate.update("DELETE FROM employee_tmp"); List employeeIds = new ArrayList<>(); for (Integer id : ids) { diff --git a/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java b/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java index f21704221b..369725bafd 100644 --- a/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java +++ b/persistence-modules/spring-persistence-simple-2/src/test/java/com/baeldung/jdbc/EmployeeDAOUnitTest.java @@ -98,5 +98,10 @@ public class EmployeeDAOUnitTest { assertEquals(1, employees.get(0).getId()); assertEquals(3, employees.get(1).getId()); assertEquals(4, employees.get(2).getId()); + + ids.clear(); + ids.add(2); + employees = employeeDAO.getEmployeesFromLargeIdList(ids); + assertEquals(1, employees.size()); } } From c68c7648a3361ee26f35356e618ddc9ab189d3f0 Mon Sep 17 00:00:00 2001 From: Gang Wu Date: Sat, 18 Apr 2020 12:48:37 -0600 Subject: [PATCH 3/5] BAEL-3961 Remove address field of Employee class. --- .../main/java/com/baeldung/jdbc/Employee.java | 17 ++++------------- .../java/com/baeldung/jdbc/EmployeeDAO.java | 11 ++++++----- .../src/main/resources/jdbc/schema.sql | 3 +-- .../src/main/resources/jdbc/test-data.sql | 8 ++++---- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java index d5f87ca3df..bd6fe0fb15 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/Employee.java @@ -7,13 +7,11 @@ public class Employee { private String lastName; - private String address; - public Employee(int id, String firstName, String lastName, String address) { - setId(id); - setFirstName(firstName); - setLastName(lastName); - setAddress(address); + public Employee(int id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; } public int getId() { @@ -40,12 +38,5 @@ public class Employee { this.lastName = lastName; } - public String getAddress() { - return address; - } - - public void setAddress(final String address) { - this.address = address; - } } diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index 25d280ad12..8637f6f851 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -30,23 +30,22 @@ public class EmployeeDAO { SqlParameterSource parameters = new MapSqlParameterSource("ids", ids); List employees = namedJdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (:ids)", parameters, - (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"), rs.getString("address"))); + (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"))); return employees; } public List getEmployeesFromIdList(List ids) { String inSql = String.join(",", Collections.nCopies(ids.size(), "?")); - List employees = jdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (" + inSql +")", + List employees = jdbcTemplate.query(String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql), ids.toArray(), - (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"), rs.getString("address"))); + (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"))); return employees; } public List getEmployeesFromLargeIdList(List ids) { jdbcTemplate.execute("CREATE TEMPORARY TABLE IF NOT EXISTS employee_tmp (id INT NOT NULL)"); - jdbcTemplate.update("DELETE FROM employee_tmp"); List employeeIds = new ArrayList<>(); for (Integer id : ids) { @@ -55,7 +54,9 @@ public class EmployeeDAO { jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds); List employees = jdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)", - (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"), rs.getString("address"))); + (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"))); + + jdbcTemplate.update("DELETE FROM employee_tmp"); return employees; } diff --git a/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/schema.sql b/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/schema.sql index 3401c5d963..be102431ca 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/schema.sql +++ b/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/schema.sql @@ -2,6 +2,5 @@ CREATE TABLE EMPLOYEE ( ID int NOT NULL PRIMARY KEY, FIRST_NAME varchar(255), - LAST_NAME varchar(255), - ADDRESS varchar(255) + LAST_NAME varchar(255) ); \ No newline at end of file diff --git a/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/test-data.sql b/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/test-data.sql index c1669c156d..5421c09849 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/test-data.sql +++ b/persistence-modules/spring-persistence-simple-2/src/main/resources/jdbc/test-data.sql @@ -1,4 +1,4 @@ -INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada'); -INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA'); -INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland'); -INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA'); \ No newline at end of file +INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling'); +INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth'); +INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds'); +INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie'); \ No newline at end of file From 8985f601a7c9b32951f2fb369092f8ab89ca0741 Mon Sep 17 00:00:00 2001 From: Gang Wu Date: Wed, 22 Apr 2020 22:15:54 -0600 Subject: [PATCH 4/5] BAEL-3961 move the sql string into a new line to improve readability. --- .../src/main/java/com/baeldung/jdbc/EmployeeDAO.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index 8637f6f851..45f206a2b9 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -37,7 +37,8 @@ public class EmployeeDAO { public List getEmployeesFromIdList(List ids) { String inSql = String.join(",", Collections.nCopies(ids.size(), "?")); - List employees = jdbcTemplate.query(String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql), + List employees = jdbcTemplate.query( + String.format("SELECT * FROM EMPLOYEE WHERE id IN (%s)", inSql), ids.toArray(), (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"))); @@ -53,7 +54,8 @@ public class EmployeeDAO { } jdbcTemplate.batchUpdate("INSERT INTO employee_tmp VALUES(?)", employeeIds); - List employees = jdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)", + List employees = jdbcTemplate.query( + "SELECT * FROM EMPLOYEE WHERE id IN (SELECT id FROM employee_tmp)", (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name"))); jdbcTemplate.update("DELETE FROM employee_tmp"); From 38f62ad24d646f18d66019eb808861462868ad80 Mon Sep 17 00:00:00 2001 From: Gang Wu Date: Wed, 22 Apr 2020 22:36:18 -0600 Subject: [PATCH 5/5] BAEL-3961 move the sql string into a new line to improve readability. --- .../src/main/java/com/baeldung/jdbc/EmployeeDAO.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java index 45f206a2b9..2ea42381eb 100644 --- a/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java +++ b/persistence-modules/spring-persistence-simple-2/src/main/java/com/baeldung/jdbc/EmployeeDAO.java @@ -28,7 +28,8 @@ public class EmployeeDAO { public List getEmployeesFromIdListNamed(List ids) { SqlParameterSource parameters = new MapSqlParameterSource("ids", ids); - List employees = namedJdbcTemplate.query("SELECT * FROM EMPLOYEE WHERE id IN (:ids)", + List employees = namedJdbcTemplate.query( + "SELECT * FROM EMPLOYEE WHERE id IN (:ids)", parameters, (rs, rowNum) -> new Employee(rs.getInt("id"), rs.getString("first_name"), rs.getString("last_name")));