Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/resumes.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
storage.dir=/Users/vladimirsafronov/Desktop/java/projects/basejava/storage
db.url=jdbc:postgresql://localhost:5432/resumes
db.url=jdbc:postgresql://localhost:5433/resumes
db.user=postgres
db.password=admin
17 changes: 17 additions & 0 deletions src/ru/javawebinar/basejava/sql/SqlHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import ru.javawebinar.basejava.exception.StorageException;

public class SqlHelper {

private final ConnectionFactory connectionFactory;

public SqlHelper(ConnectionFactory connectionFactory) {
Expand All @@ -24,4 +25,20 @@ public <T> T execute(String query, SqlExecutor<T> sqlExecutor) {
throw new StorageException(e);
}
}

public <T> T transactionalExecute(SqlTransaction<T> executor) {
try (Connection conn = connectionFactory.getConnection()) {
try {
conn.setAutoCommit(false);
T res = executor.execute(conn);
conn.commit();
return res;
} catch (SQLException e) {
conn.rollback();
throw ExceptionUtil.convertException(e);
}
} catch (SQLException e) {
throw new StorageException(e);
}
}
}
9 changes: 9 additions & 0 deletions src/ru/javawebinar/basejava/sql/SqlTransaction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package ru.javawebinar.basejava.sql;

import java.sql.Connection;
import java.sql.SQLException;

public interface SqlTransaction<T> {

T execute(Connection conn) throws SQLException;
}
91 changes: 65 additions & 26 deletions src/ru/javawebinar/basejava/storage/SqlStorage.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package ru.javawebinar.basejava.storage;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import ru.javawebinar.basejava.exception.NotExistStorageException;
Expand All @@ -25,33 +29,33 @@ public void clear() {

@Override
public void update(Resume r) {
sqlHelper.<Void>execute("UPDATE resume SET full_name = ? WHERE uuid = ?", ps -> {
ps.setString(1, r.getFullName());
ps.setString(2, r.getUuid());
if (ps.executeUpdate() == 0) {
throw new NotExistStorageException(r.getUuid());
sqlHelper.transactionalExecute(conn -> {
try (PreparedStatement ps = conn.prepareStatement(
"UPDATE resume SET full_name = ? WHERE uuid = ?")) {
ps.setString(1, r.getFullName());
ps.setString(2, r.getUuid());
if (ps.executeUpdate() == 0) {
throw new NotExistStorageException(r.getUuid());
}
deleteContacts(conn, r);
insertContacts(conn, r);
return null;
}
return null;
});
}

@Override
public void save(Resume r) {
sqlHelper.<Void>execute("INSERT INTO resume (uuid, full_name) VALUES (?,?)", ps -> {
ps.setString(1, r.getUuid());
ps.setString(2, r.getFullName());
ps.execute();
sqlHelper.transactionalExecute(conn -> {
try (PreparedStatement ps = conn.prepareStatement(
"INSERT INTO resume (uuid, full_name) VALUES (?,?)")) {
ps.setString(1, r.getUuid());
ps.setString(2, r.getFullName());
ps.execute();
}
insertContacts(conn, r);
return null;
});
for (Map.Entry<ContactType, String> e : r.getContacts().entrySet()) {
sqlHelper.<Void>execute("INSERT INTO contact (resume_uuid, type, value) VALUES (?,?,?)",
ps -> {
ps.setString(1, r.getUuid());
ps.setString(2, e.getKey().name());
ps.setString(3, e.getValue());
return null;
});
}
}

@Override
Expand All @@ -67,9 +71,7 @@ public Resume get(String uuid) {
}
Resume resume = new Resume(uuid, rs.getString("full_name"));
do {
String value = rs.getString("value");
ContactType type = ContactType.valueOf(rs.getString("type"));
resume.addContact(type, value);
addContact(rs, resume);
} while (rs.next());
return resume;
});
Expand All @@ -88,13 +90,22 @@ public void delete(String uuid) {

@Override
public List<Resume> getAllSorted() {
return sqlHelper.execute("SELECT * FROM resume ORDER BY full_name, uuid", ps -> {
return sqlHelper.execute("SELECT * FROM resume r " +
" LEFT JOIN contact c " +
" ON r.uuid = c.resume_uuid" +
" ORDER BY full_name, uuid", ps -> {
ResultSet rs = ps.executeQuery();
List<Resume> list = new ArrayList<>();
Map<String, Resume> map = new LinkedHashMap<>();
while (rs.next()) {
list.add(new Resume(rs.getString("uuid"), rs.getString("full_name")));
String uuid = rs.getString("uuid");
Resume r = map.get(uuid);
if (r == null) {
r = new Resume(uuid, rs.getString("full_name"));
map.put(uuid, r);
}
addContact(rs, r);
}
return list;
return new ArrayList<>(map.values());
});
}

Expand All @@ -105,4 +116,32 @@ public int size() {
return rs.next() ? rs.getInt("count") : 0;
});
}

private void deleteContacts(Connection conn, Resume r) {
sqlHelper.execute("DELETE FROM contact WHERE resume_uuid = ?", ps -> {
ps.setString(1, r.getUuid());
ps.execute();
return null;
});
}

private void insertContacts(Connection conn, Resume r) throws SQLException {
try (PreparedStatement ps = conn.prepareStatement
("INSERT INTO contact (resume_uuid, type, value) VALUES (?,?,?)")) {
for (Map.Entry<ContactType, String> e : r.getContacts().entrySet()) {
ps.setString(1, r.getUuid());
ps.setString(2, e.getKey().name());
ps.setString(3, e.getValue());
ps.addBatch();
}
ps.executeBatch();
}
}

private void addContact(ResultSet rs, Resume r) throws SQLException {
String value = rs.getString("value");
if (value != null) {
r.addContact(ContactType.valueOf(rs.getString("type")), value);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resume>
<uuid>d7e81904-29f4-462e-ae33-6f89f2b365bb</uuid>
<uuid>357d7d32-d69d-4bc8-bc6d-e1423544d4d6</uuid>
<fullName>Name3</fullName>
<contacts/>
<sections/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resume>
<uuid>d487ad02-280e-488a-b25d-ac45f1686728</uuid>
<uuid>84d3d6d8-ed87-4f4a-85d0-fd7b64af8518</uuid>
<fullName>Name2</fullName>
<contacts/>
<sections/>
Expand Down
7 changes: 0 additions & 7 deletions storage/9ae5ec0a-5255-4885-9867-660ed5a57e1b

This file was deleted.

20 changes: 20 additions & 0 deletions storage/9be342f4-a735-4fef-a4c9-64970eee716c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<resume>
<uuid>9be342f4-a735-4fef-a4c9-64970eee716c</uuid>
<fullName>Name1</fullName>
<contacts>
<entry>
<key>MOBILE_PHONE</key>
<value>+79877654321</value>
</entry>
<entry>
<key>SKYPE</key>
<value>newSkype</value>
</entry>
<entry>
<key>EMAIL</key>
<value>[email protected]</value>
</entry>
</contacts>
<sections/>
</resume>
17 changes: 14 additions & 3 deletions test/ru/javawebinar/basejava/storage/AbstractStorageTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.io.File;
import java.time.Month;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -39,8 +40,12 @@ protected AbstractStorageTest(Storage storage) {
R3 = new Resume(UUID_3, "Name3");
R4 = new Resume(UUID_4, "Name4");

// R1.addContact(ContactType.MOBILE_PHONE, "+79001234567");
// R1.addContact(ContactType.EMAIL, "[email protected]");
R1.addContact(ContactType.MOBILE_PHONE, "+79001234567");
R1.addContact(ContactType.EMAIL, "[email protected]");
R4.addContact(ContactType.SKYPE, "Skype");
R4.addContact(ContactType.MOBILE_PHONE, "+76666666666");


// R1.addSection(SectionType.OBJECTIVE, new SectionLine("Objective"));
// R1.addSection(SectionType.PERSONAL, new SectionLine("Personal data"));
// R1.addSection(SectionType.ACHIEVEMENT,
Expand Down Expand Up @@ -80,6 +85,9 @@ public void setUp() {
@Test
public void update() {
Resume newResume = new Resume(UUID_1, "New Name");
R1.addContact(ContactType.EMAIL, "[email protected]");
R1.addContact(ContactType.SKYPE, "newSkype");
R1.addContact(ContactType.MOBILE_PHONE, "+79877654321");
storage.update(newResume);
Assertions.assertEquals(newResume, storage.get(UUID_1));
}
Expand Down Expand Up @@ -139,7 +147,10 @@ public void getNotExist() throws Exception {
public void getAllSorted() throws Exception {
List<Resume> testStorage = storage.getAllSorted();
Assertions.assertEquals(3, testStorage.size());
Assertions.assertEquals(testStorage, Arrays.asList(R1, R2, R3));
List<Resume> sortedList = Arrays.asList(R1, R2, R3);
Collections.sort(sortedList);
Assertions.assertEquals(sortedList, testStorage);

}

@Test
Expand Down