diff --git a/persistence-modules/java-sql2o/README.md b/persistence-modules/java-sql2o/README.md
new file mode 100644
index 0000000000..a86e45f1c8
--- /dev/null
+++ b/persistence-modules/java-sql2o/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [A Guide to Sql2o](http://www.baeldung.com/sql2o)
diff --git a/persistence-modules/java-sql2o/pom.xml b/persistence-modules/java-sql2o/pom.xml
new file mode 100644
index 0000000000..fe5a0e5dc8
--- /dev/null
+++ b/persistence-modules/java-sql2o/pom.xml
@@ -0,0 +1,54 @@
+
+
+ 4.0.0
+ java-sql2o
+ 1.0-SNAPSHOT
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ 8
+
+
+
+
+ java-sql2o
+
+
+ persistence-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+ ..
+
+
+
+
+ org.sql2o
+ sql2o
+ ${sql2o.version}
+
+
+ org.hsqldb
+ hsqldb
+ ${hsqldb.version}
+ test
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+
+ 2.4.0
+ 4.12
+ 1.6.0
+
+
+
diff --git a/persistence-modules/java-sql2o/src/test/java/com/baeldung/persistence/sql2o/Sql2oIntegrationTest.java b/persistence-modules/java-sql2o/src/test/java/com/baeldung/persistence/sql2o/Sql2oIntegrationTest.java
new file mode 100644
index 0000000000..4429b1578c
--- /dev/null
+++ b/persistence-modules/java-sql2o/src/test/java/com/baeldung/persistence/sql2o/Sql2oIntegrationTest.java
@@ -0,0 +1,340 @@
+package com.baeldung.persistence.sql2o;
+
+import org.junit.Test;
+import org.sql2o.Connection;
+import org.sql2o.Query;
+import org.sql2o.ResultSetIterable;
+import org.sql2o.Sql2o;
+import org.sql2o.data.Row;
+import org.sql2o.data.Table;
+
+import java.sql.SQLException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import static org.junit.Assert.*;
+
+public class Sql2oIntegrationTest {
+
+ @Test
+ public void whenSql2oCreated_thenSuccess() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ java.sql.Connection jdbcConnection = connection.getJdbcConnection();
+ assertFalse(jdbcConnection.isClosed());
+ } catch (SQLException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Test
+ public void whenTableCreated_thenInsertIsPossible() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_1 (id integer identity, name varchar(50), url varchar(100))").executeUpdate();
+ assertEquals(0, connection.getResult());
+ connection.createQuery("INSERT INTO PROJECT_1 VALUES (1, 'tutorials', 'github.com/eugenp/tutorials')").executeUpdate();
+ assertEquals(1, connection.getResult());
+ connection.createQuery("drop table PROJECT_1").executeUpdate();
+ }
+ }
+
+ @Test
+ public void whenIdentityColumn_thenInsertReturnsNewId() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_2 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
+ Query query = connection.createQuery(
+ "INSERT INTO PROJECT_2 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')",
+ true);
+ assertEquals(0, query.executeUpdate().getKey());
+ query = connection.createQuery("INSERT INTO PROJECT_2 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')",
+ true);
+ assertEquals(1, query.executeUpdate().getKeys()[0]);
+ connection.createQuery("drop table PROJECT_2").executeUpdate();
+ }
+ }
+
+ @Test
+ public void whenSelect_thenResultsAreObjects() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_3 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_3 (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')").executeUpdate();
+ Query query = connection.createQuery("select * from PROJECT_3 order by id");
+ List list = query.executeAndFetch(Project.class);
+
+ assertEquals("tutorials", list.get(0).getName());
+ assertEquals("REST with Spring", list.get(1).getName());
+
+ connection.createQuery("drop table PROJECT_3").executeUpdate();
+ }
+ }
+
+ @Test
+ public void whenSelectAlias_thenResultsAreObjects() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_4 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_4 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_4 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
+ Query query = connection.createQuery("select NAME, URL, creation_date as creationDate from PROJECT_4 order by id");
+ List list = query.executeAndFetch(Project.class);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ assertEquals("2019-01-01", sdf.format(list.get(0).getCreationDate()));
+ assertEquals("2019-02-01", sdf.format(list.get(1).getCreationDate()));
+
+ connection.createQuery("drop table PROJECT_4").executeUpdate();
+ }
+ }
+
+ @Test
+ public void whenSelectMapping_thenResultsAreObjects() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
+ Query query = connection.createQuery("select * from PROJECT_5 order by id")
+ .addColumnMapping("CrEaTiOn_date", "creationDate");
+ List list = query.executeAndFetch(Project.class);
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ assertEquals("2019-01-01", sdf.format(list.get(0).getCreationDate()));
+ assertEquals("2019-02-01", sdf.format(list.get(1).getCreationDate()));
+
+ connection.createQuery("drop table PROJECT_5").executeUpdate();
+ }
+ }
+
+ @Test
+ public void whenSelectCount_thenResultIsScalar() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_6 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_6 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_6 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
+ Query query = connection.createQuery("select count(*) from PROJECT_6");
+ assertEquals(2.0, query.executeScalar(Double.TYPE), 0.001);
+ connection.createQuery("drop table PROJECT_6").executeUpdate();
+ }
+ }
+
+ @Test
+ public void whenFetchTable_thenResultsAreMaps() {
+ Sql2o sql2o = new Sql2o("jdbc:hsqldb:mem:testDB", "sa", "");
+ try(Connection connection = sql2o.open()) {
+ connection.createQuery("create table PROJECT_5 (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100), creation_date date)").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('tutorials', 'github.com/eugenp/tutorials', '2019-01-01')").executeUpdate();
+ connection.createQuery("INSERT INTO PROJECT_5 (NAME, URL, creation_date) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring', '2019-02-01')").executeUpdate();
+ Query query = connection.createQuery("select * from PROJECT_5 order by id");
+ Table table = query.executeAndFetchTable();
+ List