Skip to content

Commit 5305b32

Browse files
committed
Spring JDBC Template
1 parent 4ab2707 commit 5305b32

7 files changed

Lines changed: 175 additions & 19 deletions

File tree

build.gradle

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,43 @@
1+
import org.flywaydb.gradle.task.FlywayMigrateTask
2+
13
plugins {
24
id "java"
35
id "org.springframework.boot" version "1.5.4.RELEASE"
6+
id "org.flywaydb.flyway" version "4.2.0"
47
}
58

69
repositories {
710
mavenCentral()
811
}
912

1013
dependencies {
11-
compile("org.springframework.boot:spring-boot-starter-web")
1214
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.1")
15+
compile("org.springframework.boot:spring-boot-starter-jdbc")
16+
compile("org.springframework.boot:spring-boot-starter-web")
17+
18+
compile("mysql:mysql-connector-java:6.0.6")
19+
1320
testCompile("org.springframework.boot:spring-boot-starter-test")
1421
}
15-
22+
def developmentDbUrl = "jdbc:mysql://localhost:3306/tracker_dev?user=tracker&useSSL=false&useTimezone=true&serverTimezone=UTC&useLegacyDatetimeCode=false"
1623
bootRun.environment([
1724
"WELCOME_MESSAGE": "hello",
25+
"SPRING_DATASOURCE_URL": developmentDbUrl,
1826
])
1927

28+
def testDbUrl = "jdbc:mysql://localhost:3306/tracker_test?user=tracker&useSSL=false&useTimezone=true&serverTimezone=UTC&useLegacyDatetimeCode=false"
2029
test.environment([
2130
"WELCOME_MESSAGE": "Hello from test",
22-
])
31+
"SPRING_DATASOURCE_URL": testDbUrl,
32+
])
33+
34+
flyway {
35+
url = developmentDbUrl
36+
user = "tracker"
37+
password = ""
38+
locations = ["filesystem:databases/tracker/migrations"]
39+
}
40+
41+
task testMigrate(type: FlywayMigrateTask) {
42+
url = testDbUrl
43+
}

src/main/java/io/pivotal/pal/tracker/PalTrackerApplication.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
import org.springframework.boot.autoconfigure.SpringBootApplication;
99
import org.springframework.context.annotation.Bean;
1010
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
11-
import test.pivotal.pal.tracker.InMemoryTimeEntryRepository;
11+
import test.pivotal.pal.tracker.JdbcTimeEntryRepository;
12+
13+
import javax.sql.DataSource;
1214

1315
@SpringBootApplication
1416
public class PalTrackerApplication {
@@ -18,8 +20,8 @@ public static void main(String[] args) {
1820
}
1921

2022
@Bean
21-
public TimeEntryRepository timeEntryRepository() {
22-
return new InMemoryTimeEntryRepository();
23+
public TimeEntryRepository timeEntryRepository(DataSource dataSource) {
24+
return new JdbcTimeEntryRepository(dataSource);
2325
}
2426

2527
@Bean

src/main/java/io/pivotal/pal/tracker/TimeEntry.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,20 @@ public long getId() {
3232
return this.id;
3333
}
3434

35-
public void setId(long id) {
36-
this.id = id;
35+
public long getProjectId() {
36+
return projectId;
37+
}
38+
39+
public long getUserId() {
40+
return userId;
41+
}
42+
43+
public LocalDate getDate() {
44+
return date;
45+
}
46+
47+
public int getHours() {
48+
return hours;
3749
}
3850

3951
public boolean equals(Object o) {
@@ -47,11 +59,11 @@ public boolean equals(Object o) {
4759
}
4860

4961
public String toString() {
50-
return "TimeEntry(projectId=" + projectId +
62+
return "TimeEntry(id=" + id +
63+
", projectId=" + projectId +
5164
", userId=" + userId +
5265
", date=" + date +
5366
", hours=" + hours +
5467
")";
55-
5668
}
5769
}

src/main/java/test/pivotal/pal/tracker/InMemoryTimeEntryRepository.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ public class InMemoryTimeEntryRepository implements TimeEntryRepository {
1313
private Map<Long, TimeEntry> store = new HashMap<>();
1414

1515
public TimeEntry create(TimeEntry timeEntry) {
16-
timeEntry.setId(nextTimeEntryId);
17-
store.put(nextTimeEntryId, timeEntry);
16+
final TimeEntry newTimeEntry = new TimeEntry(
17+
nextTimeEntryId,
18+
timeEntry.getProjectId(),
19+
timeEntry.getUserId(),
20+
timeEntry.getDate(),
21+
timeEntry.getHours()
22+
);
23+
24+
store.put(nextTimeEntryId, newTimeEntry);
1825
nextTimeEntryId += 1;
19-
return timeEntry;
26+
27+
return newTimeEntry;
2028
}
2129

2230
public TimeEntry find(long timeEntryId) {
@@ -28,10 +36,17 @@ public List<TimeEntry> list() {
2836
}
2937

3038
public TimeEntry update(long timeEntryId, TimeEntry timeEntry) {
31-
final TimeEntry old = store.get(timeEntryId);
32-
timeEntry.setId(old.getId());
33-
store.put(timeEntry.getId(), timeEntry);
34-
return timeEntry;
39+
final TimeEntry updatedTimeEntry = new TimeEntry(
40+
timeEntryId,
41+
timeEntry.getProjectId(),
42+
timeEntry.getUserId(),
43+
timeEntry.getDate(),
44+
timeEntry.getHours()
45+
);
46+
47+
store.put(timeEntryId, updatedTimeEntry);
48+
49+
return updatedTimeEntry;
3550
}
3651

3752
public void delete(long timeEntryId) {
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package test.pivotal.pal.tracker;
2+
3+
import io.pivotal.pal.tracker.TimeEntry;
4+
import io.pivotal.pal.tracker.TimeEntryRepository;
5+
import org.springframework.jdbc.core.JdbcTemplate;
6+
import org.springframework.jdbc.core.ResultSetExtractor;
7+
import org.springframework.jdbc.core.RowMapper;
8+
import org.springframework.jdbc.support.GeneratedKeyHolder;
9+
import org.springframework.jdbc.support.KeyHolder;
10+
11+
import javax.sql.DataSource;
12+
import java.sql.Date;
13+
import java.sql.PreparedStatement;
14+
import java.sql.Statement;
15+
import java.util.List;
16+
17+
public class JdbcTimeEntryRepository implements TimeEntryRepository {
18+
private final JdbcTemplate jdbcTemplate;
19+
private final RowMapper<TimeEntry> rowMapper = (rs1, rowNum) -> new TimeEntry(
20+
rs1.getLong("id"),
21+
rs1.getLong("project_id"),
22+
rs1.getLong("user_id"),
23+
rs1.getDate("date").toLocalDate(),
24+
rs1.getInt("hours")
25+
);
26+
private final ResultSetExtractor<TimeEntry> resultSetExtractor = rs -> rs.next() ? rowMapper.mapRow(rs, 1) : null;
27+
28+
public JdbcTimeEntryRepository(DataSource dataSource) {
29+
this.jdbcTemplate = new JdbcTemplate(dataSource);
30+
}
31+
32+
@Override
33+
public TimeEntry create(TimeEntry timeEntry) {
34+
final String insertSql = "INSERT INTO time_entries (project_id, user_id, date, hours) VALUES (?, ?, ?, ?)";
35+
36+
KeyHolder keyHolder = new GeneratedKeyHolder();
37+
jdbcTemplate.update(
38+
connection -> {
39+
PreparedStatement statement = connection.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
40+
41+
statement.setLong(1, timeEntry.getProjectId());
42+
statement.setLong(2, timeEntry.getUserId());
43+
statement.setDate(3, Date.valueOf(timeEntry.getDate()));
44+
statement.setInt(4, timeEntry.getHours());
45+
46+
return statement;
47+
},
48+
keyHolder
49+
);
50+
51+
return find(keyHolder.getKey().intValue());
52+
}
53+
54+
@Override
55+
public TimeEntry find(long timeEntryId) {
56+
final String findSql = "SELECT id, project_id, user_id, date, hours FROM time_entries WHERE id = ?";
57+
58+
return jdbcTemplate.query(
59+
findSql,
60+
new Object[]{timeEntryId},
61+
resultSetExtractor
62+
);
63+
}
64+
65+
@Override
66+
public List<TimeEntry> list() {
67+
final String listSql = "SELECT id, project_id, user_id, date, hours FROM time_entries";
68+
69+
return jdbcTemplate.query(listSql, rowMapper);
70+
}
71+
72+
@Override
73+
public TimeEntry update(long timeEntryId, TimeEntry timeEntry) {
74+
final String updateSql = "UPDATE time_entries SET project_id = ?, user_id = ?, date = ?, hours = ? WHERE id = ?";
75+
76+
jdbcTemplate.update(
77+
updateSql,
78+
timeEntry.getProjectId(),
79+
timeEntry.getUserId(),
80+
Date.valueOf(timeEntry.getDate()),
81+
timeEntry.getHours(),
82+
timeEntryId
83+
);
84+
85+
return find(timeEntryId);
86+
}
87+
88+
@Override
89+
public void delete(long timeEntryId) {
90+
jdbcTemplate.update("DELETE FROM time_entries WHERE id = ?", timeEntryId);
91+
}
92+
}

src/test/java/test/pivotal/pal/tracker/JdbcTimeEntryRepositoryTest.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33

44
import com.mysql.cj.jdbc.MysqlDataSource;
5-
import io.pivotal.pal.tracker.JdbcTimeEntryRepository;
65
import io.pivotal.pal.tracker.TimeEntry;
76
import io.pivotal.pal.tracker.TimeEntryRepository;
87
import org.junit.Before;
@@ -22,7 +21,7 @@ public class JdbcTimeEntryRepositoryTest {
2221
private JdbcTemplate jdbcTemplate;
2322

2423
@Before
25-
public void setUp() throws Exception {
24+
public void setUp() {
2625
MysqlDataSource dataSource = new MysqlDataSource();
2726
dataSource.setUrl(System.getenv("SPRING_DATASOURCE_URL"));
2827

src/test/java/test/pivotal/pal/trackerapi/TimeEntryApiTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package test.pivotal.pal.trackerapi;
22

33
import com.jayway.jsonpath.DocumentContext;
4+
import com.mysql.cj.jdbc.MysqlDataSource;
45
import io.pivotal.pal.tracker.PalTrackerApplication;
56
import io.pivotal.pal.tracker.TimeEntry;
7+
import org.junit.Before;
68
import org.junit.Test;
79
import org.junit.runner.RunWith;
810
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,10 +14,12 @@
1214
import org.springframework.http.HttpMethod;
1315
import org.springframework.http.HttpStatus;
1416
import org.springframework.http.ResponseEntity;
17+
import org.springframework.jdbc.core.JdbcTemplate;
1518
import org.springframework.test.context.junit4.SpringRunner;
1619

1720
import java.time.LocalDate;
1821
import java.util.Collection;
22+
import java.util.TimeZone;
1923

2024
import static com.jayway.jsonpath.JsonPath.parse;
2125
import static org.assertj.core.api.Assertions.assertThat;
@@ -32,6 +36,17 @@ public class TimeEntryApiTest {
3236
private final long userId = 456L;
3337
private TimeEntry timeEntry = new TimeEntry(projectId, userId, LocalDate.parse("2017-01-08"), 8);
3438

39+
@Before
40+
public void setup() throws Exception {
41+
MysqlDataSource dataSource = new MysqlDataSource();
42+
dataSource.setUrl(System.getenv("SPRING_DATASOURCE_URL"));
43+
44+
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
45+
jdbcTemplate.execute("TRUNCATE time_entries");
46+
47+
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
48+
}
49+
3550
@Test
3651
public void testCreate() throws Exception {
3752
ResponseEntity<String> createResponse = restTemplate.postForEntity("/time-entries", timeEntry, String.class);

0 commit comments

Comments
 (0)