From 49dddfe824eef4efd53e176fc8842f96b9f29cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20Wilhelmst=C3=B6tter?= Date: Fri, 6 Jan 2017 19:14:48 +0100 Subject: [PATCH] #1: Implement PersonDAO. --- .../main/java/io/jenetics/jpx/jdbc/DAO.java | 24 +-- .../main/java/io/jenetics/jpx/jdbc/Diff.java | 7 - .../java/io/jenetics/jpx/jdbc/LinkDAO.java | 46 ++--- .../main/java/io/jenetics/jpx/jdbc/Param.java | 24 +-- .../java/io/jenetics/jpx/jdbc/PersonDAO.java | 159 ++++++++++++++++-- .../io/jenetics/jpx/jdbc/LinkDAOTest.java | 10 +- 6 files changed, 182 insertions(+), 88 deletions(-) diff --git a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/DAO.java b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/DAO.java index 6b99e623..5af4d842 100644 --- a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/DAO.java +++ b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/DAO.java @@ -30,10 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; -import java.util.function.BiPredicate; import java.util.function.Function; -import java.util.stream.Collectors; /** * Abstract DAO class @@ -90,7 +87,7 @@ static List> put( { final Map> existing = select.apply(values).stream() .collect(toMap( - value -> key.apply(value.getValue().orElse(null)), + value -> key.apply(value.optional().orElse(null)), value -> value, (a, b) -> b)); @@ -100,7 +97,7 @@ static List> put( final Diff, T> diff = Diff.of(existing, actual); final List missing = diff.missing(); final List> updated = diff - .updated((e, a) -> Objects.equals(e.getValue().orElse(null), a)) + .updated((e, a) -> Objects.equals(e.optional().orElse(null), a)) .entrySet().stream() .map(entry -> entry.getKey().map(m -> entry.getValue())) .collect(toList()); @@ -113,23 +110,6 @@ static List> put( return result; } - /* - public static Stored put( - final T value, - final SQL.Function>> select, - final SQL.Function> insert, - final SQL.Consumer> update - ) - throws SQLException - { - return select.apply(value) - .map(stored -> { - update.accept(stored); - return stored.copy(value); }) - .orElseGet(() -> insert.apply(value)); - } - */ - /** * Reads the auto increment id from the previously inserted record. * diff --git a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Diff.java b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Diff.java index 75f5f793..ca957045 100644 --- a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Diff.java +++ b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Diff.java @@ -94,13 +94,6 @@ Map updated(final BiPredicate equals) { .collect(toMap(_existing::get, _actual::get, (a, b) -> b)); } - /* -- def updated( doesEqual: (E,A) => Boolean ): Iterable[A] = { - - intersection.filter{ key: K => !doesEqual( existing(key), actual(key) ) } - - .map{ key:K => actual(key) } - - } - */ - /** * Create a new {@code Diff} object with the given existing and actual values. * diff --git a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/LinkDAO.java b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/LinkDAO.java index ab174d77..a245286d 100644 --- a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/LinkDAO.java +++ b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/LinkDAO.java @@ -25,8 +25,6 @@ import java.net.URI; import java.sql.Connection; import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -58,6 +56,7 @@ public LinkDAO(final Connection connection) { ) ); + /* ************************************************************************* * INSERT queries **************************************************************************/ @@ -96,6 +95,7 @@ public Stored insert(final Link link) return insert(singletonList(link)).get(0); } + /* ************************************************************************* * UPDATE queries **************************************************************************/ @@ -115,9 +115,9 @@ public List> update(final List> links) "WHERE id = {id}"; Batch(query).update(links, link -> asList( - Param.value("id", link.getID()), - Param.value("text", link.getValue().map(Link::getText)), - Param.value("type", link.getValue().map(Link::getType)) + Param.value("id", link.id()), + Param.value("text", link.value().getText()), + Param.value("type", link.value().getType()) )); return links; @@ -134,12 +134,20 @@ public Stored update(final Stored link) throws SQLException { return update(singletonList(link)).get(0); } + /** + * Inserts the given links into the DB. If the DB already contains the given + * link, the link is updated. + * + * @param links the links to insert or update + * @return the inserted or updated links + * @throws SQLException if the insert/update fails + */ public List> put(final List links) throws SQLException { return DAO.put( links, Link::getHref, - ll -> selectByHrefs( - ll.stream() + list -> selectByHrefs( + list.stream() .map(Link::getHref) .collect(Collectors.toList()) ), @@ -148,6 +156,7 @@ public List> put(final List links) throws SQLException { ); } + /* ************************************************************************* * SELECT queries **************************************************************************/ @@ -190,28 +199,19 @@ public SQL.Option> selectByID(final long id) .as(RowParser.singleOpt()); } - - public List> selectByHrefs(final List hrefs) - throws SQLException - { - return SQL("SELECT id, href, text, type FROM link WHERE href IN ({hrefs})") - .on(Param.values("hrefs", hrefs)) - .as(RowParser.list()); - } - /** - * Select the links by the HREF. + * Selects the links by its hrefs. * - * @param href the href to select - * @return the selected links + * @param hrefs the hrefs + * @return the link with the given hrefs currently in the DB * @throws SQLException if the select fails */ - public SQL.Option> selectByHref(final URI href) + public List> selectByHrefs(final List hrefs) throws SQLException { - return SQL("SELECT id, href, text, type FROM link WHERE href = {href}") - .on("href", href) - .as(RowParser.singleOpt()); + return SQL("SELECT id, href, text, type FROM link WHERE href IN ({hrefs})") + .on(Param.values("hrefs", hrefs)) + .as(RowParser.list()); } /** diff --git a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Param.java b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Param.java index 88ddcd43..e66bc6f5 100644 --- a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Param.java +++ b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/Param.java @@ -20,14 +20,11 @@ package io.jenetics.jpx.jdbc; import static java.lang.String.format; -import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Objects.requireNonNull; -import java.sql.SQLException; -import java.util.Collections; +import java.util.Collection; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.LongStream; @@ -42,9 +39,9 @@ final class Param { private final String _name; - private final List _values; + private final Collection _values; - private Param(final String name, final List values) { + private Param(final String name, final Collection values) { _name = requireNonNull(name); _values = requireNonNull(values); } @@ -58,7 +55,7 @@ String name() { return _name; } - List values() { + Collection values() { return _values; } @@ -81,7 +78,10 @@ public static Param value(final String name, final Object value) { return new Param(name, singletonList(value)); } - public static Param values(final String name, final List values) { + public static Param values( + final String name, + final Collection values + ) { return new Param(name, values); } @@ -94,12 +94,4 @@ public static Param values(final String name, final long... values) { ); } - /* - public static Param insert( - final String name, - final SQL.Supplier value - ) { - return new Param(name, SQL.Lazy.of(value)); - } - */ } diff --git a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/PersonDAO.java b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/PersonDAO.java index d8df157a..553cc021 100644 --- a/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/PersonDAO.java +++ b/jpx.jdbc/src/main/java/io/jenetics/jpx/jdbc/PersonDAO.java @@ -19,11 +19,16 @@ */ package io.jenetics.jpx.jdbc; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.toMap; + import java.sql.Connection; import java.sql.SQLException; -import java.util.Arrays; import java.util.List; -import java.util.Optional; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; import io.jenetics.jpx.Email; import io.jenetics.jpx.Link; @@ -55,35 +60,135 @@ private PersonDAO(final Connection conn) { ) ); + + /* ************************************************************************* + * INSERT queries + **************************************************************************/ + /** - * Insert the given link list into the DB. + * Insert the given person list into the DB. * * @param persons the persons to insert - * @return return the stored links + * @return return the stored persons * @throws SQLException if inserting fails */ public List> insert(final List persons) throws SQLException { + final Map links = putLinks(persons); + final String query = "INSERT INTO person(name, email, link_id) " + "VALUES({name}, {email}, {link_id});"; - return Batch(query).insert(persons, person -> Arrays.asList( + return Batch(query).insert(persons, person -> asList( Param.value("name", person.getName()), - Param.value("email", person.getEmail().map(Email::getAddress)) - //Param.insert("link_id", () -> insertOrUpdate(person.getLink())) + Param.value("email", person.getEmail().map(Email::getAddress)), + Param.value("link_id", person.getLink().map(links::get)) + )); + } + + private Map putLinks(final List persons) + throws SQLException + { + final List> links = dao(LinkDAO::new).put( + persons.stream() + .flatMap(p -> p.getLink().map(Stream::of).orElse(Stream.empty())) + .collect(Collectors.toList()) + ); + + return links.stream() + .collect(toMap(Stored::value, Stored::id, (a, b) -> b)); + } + + /** + * Insert the given person into the DB. + * + * @param person the person to insert + * @return return the stored person + * @throws SQLException if inserting fails + */ + public Stored insert(final Person person) throws SQLException { + return insert(singletonList(person)).get(0); + } + + + /* ************************************************************************* + * UPDATE queries + **************************************************************************/ + + /** + * Updates the given list of already inserted link objects. + * + * @param persons the persons to update + * @return the updated persons + * @throws SQLException if the update fails + */ + public List> update(final List> persons) + throws SQLException + { + final Map links = putLinks( + persons.stream() + .map(Stored::value) + .collect(Collectors.toList()) + ); + + final String query = + "UPDATE person " + + "SET name = {name}, email = {email}, link_id = {link_id} " + + "WHERE id = {id}"; + + Batch(query).update(persons, person -> asList( + Param.value("id", person.id()), + Param.value("name", person.value().getName()), + Param.value("email", person.value().getEmail().map(Email::getAddress)), + Param.value("link_id", person.value().getLink().map(links::get)) )); + + return persons; + } + + /** + * Update the given person. + * + * @param person the person to update + * @return the updated person + * @throws SQLException if the update fails + */ + public Stored update(final Stored person) + throws SQLException + { + return update(singletonList(person)).get(0); } - /* - private Long insertOrUpdate(final Optional link) throws SQLException { - return link.isPresent() - ? dao(LinkDAO::of).put(link.get()).getID() - : null; + /** + * Inserts the given persons into the DB. If the DB already contains the + * given person, the person is updated. + * + * @param persons the links to insert or update + * @return the inserted or updated links + * @throws SQLException if the insert/update fails + */ + public List> put(final List persons) + throws SQLException + { + return DAO.put( + persons, + Person::getName, + list -> selectByNames( + list.stream() + .flatMap(p -> p.getName() + .map(Stream::of).orElse(Stream.empty())) + .collect(Collectors.toList()) + ), + this::insert, + this::update + ); } - */ + /* ************************************************************************* + * SELECT queries + **************************************************************************/ public List> select() throws SQLException { final String query = @@ -94,11 +199,37 @@ public List> select() throws SQLException { "link.text AS link_text, " + "link.type AS link_type " + "FROM person " + - "INNER JOIN link ON (person.link_id = link.id)"; + "OUTER JOIN link ON (person.link_id = link.id)"; return SQL(query).as(RowParser.list()); } + /** + * Selects the links by its hrefs. + * + * @param names the person names + * @return the link with the given hrefs currently in the DB + * @throws SQLException if the select fails + */ + public List> selectByNames(final List names) + throws SQLException + { + final String query = + "SELECT id, " + + "name, " + + "email, " + + "link.href AS link_href, " + + "link.text AS link_text, " + + "link.type AS link_type " + + "FROM person " + + "OUTER JOIN link ON (person.link_id = link.id)" + + "WHERE name IN ({names})"; + + return SQL(query) + .on(Param.values("names", names)) + .as(RowParser.list()); + } + public static PersonDAO of(final Connection conn) { return new PersonDAO(conn); } diff --git a/jpx.jdbc/src/test/java/io/jenetics/jpx/jdbc/LinkDAOTest.java b/jpx.jdbc/src/test/java/io/jenetics/jpx/jdbc/LinkDAOTest.java index 4010ed00..1a6e3f2e 100644 --- a/jpx.jdbc/src/test/java/io/jenetics/jpx/jdbc/LinkDAOTest.java +++ b/jpx.jdbc/src/test/java/io/jenetics/jpx/jdbc/LinkDAOTest.java @@ -39,7 +39,7 @@ import io.jenetics.jpx.LinkTest; /** - * @author Franz Wilhelmstötter + * @author Franz Wilhelmstötter */ public class LinkDAOTest { @@ -81,14 +81,12 @@ public void insert() throws SQLException { Assert.assertEquals( db.transaction(conn -> { return LinkDAO.of(conn) - .selectByID(link.getID()) + .selectByID(link.id()) .orElseThrow(NoSuchElementException::new); }), link ); } - - stored.forEach(System.out::println); } @Test(dependsOnMethods = "insert") @@ -99,7 +97,7 @@ public void select() throws SQLException { Assert.assertEquals( existing.stream() - .map(l -> l.getValue().orElse(null)) + .map(l -> l.optional().orElse(null)) .collect(Collectors.toSet()), links.stream() .collect(Collectors.toSet()) @@ -145,7 +143,7 @@ public void put() throws SQLException { Assert.assertEquals( dao.select().stream() - .map(l -> l.getValue().orElse(null)) + .map(l -> l.optional().orElse(null)) .collect(Collectors.toSet()), links.stream() .collect(Collectors.toSet())