diff --git a/pom.xml b/pom.xml index d0e3632..c22bfe7 100644 --- a/pom.xml +++ b/pom.xml @@ -8,17 +8,17 @@ com.gullerya 1.0-SNAPSHOT - SQL DSL (Java) + SQL DSL - SQL queries builder and executor, implemented in Java. Featured by strongly typed validations, simplicity of - use. + SQL queries builder and executor. + JPA standard annotations compliant, featured by strongly typed validations, very simple to use. https://github.com/gullerya/sql-dsl-java - The Apache License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt + ISC License + https://opensource.org/licenses/ISC @@ -40,13 +40,15 @@ 2.2 - 1.7.32 + 1.7.36 17 3.1.0 3.2.0 3.8.1 + + 3.2.0 3.2.0 3.3.1 @@ -59,14 +61,14 @@ true - 2.14.1 - 5.8.1 + 2.17.0 + 5.8.2 4.4.2 3.0.0-M5 0.8.7 - 5.0.0 - 9.4.0.jre16 - 42.3.1 + 5.0.1 + 42.3.3 + 10.2.0.jre17 diff --git a/src/main/java/com/gullerya/sqldsl/Join.java b/src/main/java/com/gullerya/sqldsl/Join.java index e8fcd14..1a7f2fb 100644 --- a/src/main/java/com/gullerya/sqldsl/Join.java +++ b/src/main/java/com/gullerya/sqldsl/Join.java @@ -2,10 +2,16 @@ import com.gullerya.sqldsl.api.statements.Select; +import java.util.Map; + public interface Join { - void inner(Select.SelectDownstream selectionA, Select.SelectDownstream selectionB); + static Map inner(Select.SelectDownstream... joiners) { + return null; + } - void toward(Class mainEntity, Select.SelectDownstream selectionA, Select.SelectDownstream selectionB); + static Map toward(Select.SelectDownstream primaryEntity, Select.SelectDownstream... joiners) { + return null; + } } diff --git a/src/main/java/com/gullerya/sqldsl/UpdateTermAction.java b/src/main/java/com/gullerya/sqldsl/UpdateTermAction.java deleted file mode 100644 index ded6eca..0000000 --- a/src/main/java/com/gullerya/sqldsl/UpdateTermAction.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.gullerya.sqldsl; - -public interface UpdateTermAction { - - int all(); -} diff --git a/src/main/java/com/gullerya/sqldsl/api/clauses/Where.java b/src/main/java/com/gullerya/sqldsl/api/clauses/Where.java index f54615a..bd60f08 100644 --- a/src/main/java/com/gullerya/sqldsl/api/clauses/Where.java +++ b/src/main/java/com/gullerya/sqldsl/api/clauses/Where.java @@ -11,14 +11,7 @@ public interface Where { S where(WhereClause where); - final class WhereFieldValuePair { - public final String column; - public final Object value; - - private WhereFieldValuePair(String column, Object value) { - this.column = column; - this.value = value; - } + final record WhereFieldValuePair(String column, Object value) { } /** diff --git a/src/main/java/com/gullerya/sqldsl/api/statements/Delete.java b/src/main/java/com/gullerya/sqldsl/api/statements/Delete.java index 08dca20..7d051c5 100644 --- a/src/main/java/com/gullerya/sqldsl/api/statements/Delete.java +++ b/src/main/java/com/gullerya/sqldsl/api/statements/Delete.java @@ -17,5 +17,5 @@ public interface Delete { * @param whereClause where clause; MUST NOT be NULL * @return number of affected rows */ - int deleteAll(Where.WhereClause whereClause); + int delete(Where.WhereClause whereClause); } diff --git a/src/main/java/com/gullerya/sqldsl/api/statements/Select.java b/src/main/java/com/gullerya/sqldsl/api/statements/Select.java index a33d0d9..b613493 100644 --- a/src/main/java/com/gullerya/sqldsl/api/statements/Select.java +++ b/src/main/java/com/gullerya/sqldsl/api/statements/Select.java @@ -2,7 +2,6 @@ import java.util.Set; -import com.gullerya.sqldsl.SelectTermAction; import com.gullerya.sqldsl.api.clauses.GroupBy; import com.gullerya.sqldsl.api.clauses.Having; import com.gullerya.sqldsl.api.clauses.OrderBy; diff --git a/src/main/java/com/gullerya/sqldsl/SelectTermAction.java b/src/main/java/com/gullerya/sqldsl/api/statements/SelectTermAction.java similarity index 73% rename from src/main/java/com/gullerya/sqldsl/SelectTermAction.java rename to src/main/java/com/gullerya/sqldsl/api/statements/SelectTermAction.java index dfdc911..717a7aa 100644 --- a/src/main/java/com/gullerya/sqldsl/SelectTermAction.java +++ b/src/main/java/com/gullerya/sqldsl/api/statements/SelectTermAction.java @@ -1,8 +1,8 @@ -package com.gullerya.sqldsl; +package com.gullerya.sqldsl.api.statements; import java.util.List; -public interface SelectTermAction { +interface SelectTermAction { /** * read a single entity @@ -21,20 +21,20 @@ public interface SelectTermAction { List readAll(); /** - * read all entities matching query, if any + * read a limited number of entities matching query, if any * - no offset applied * * @param limit limit number; MUST be greater than 0 * @return list of entities; MAY be an EMPTY list; MAY NOT be NULL */ - List readAll(int limit); + List read(int limit); /** - * read all entities matching query, if any + * read a limited number of entities matching query, if any * * @param offset offset number; MUST be greater than 0 * @param limit limit number; MUST be greater than 0 * @return list of entities; MAY be an EMPTY list; MAY NOT be NULL */ - List readAll(int offset, int limit); + List read(int offset, int limit); } diff --git a/src/main/java/com/gullerya/sqldsl/api/statements/Update.java b/src/main/java/com/gullerya/sqldsl/api/statements/Update.java index 63343ab..7124194 100644 --- a/src/main/java/com/gullerya/sqldsl/api/statements/Update.java +++ b/src/main/java/com/gullerya/sqldsl/api/statements/Update.java @@ -1,7 +1,6 @@ package com.gullerya.sqldsl.api.statements; import com.gullerya.sqldsl.Literal; -import com.gullerya.sqldsl.UpdateTermAction; import com.gullerya.sqldsl.api.clauses.Where; public interface Update { diff --git a/src/main/java/com/gullerya/sqldsl/api/statements/UpdateTermAction.java b/src/main/java/com/gullerya/sqldsl/api/statements/UpdateTermAction.java new file mode 100644 index 0000000..705c0ad --- /dev/null +++ b/src/main/java/com/gullerya/sqldsl/api/statements/UpdateTermAction.java @@ -0,0 +1,6 @@ +package com.gullerya.sqldsl.api.statements; + +interface UpdateTermAction { + + int all(); +} diff --git a/src/main/java/com/gullerya/sqldsl/impl/EntityDALImpl.java b/src/main/java/com/gullerya/sqldsl/impl/EntityDALImpl.java index 1989aa4..cbc1358 100644 --- a/src/main/java/com/gullerya/sqldsl/impl/EntityDALImpl.java +++ b/src/main/java/com/gullerya/sqldsl/impl/EntityDALImpl.java @@ -11,12 +11,11 @@ import com.gullerya.sqldsl.EntityDAL; import com.gullerya.sqldsl.Literal; import com.gullerya.sqldsl.api.clauses.Where; -import com.gullerya.sqldsl.api.statements.Delete; -import com.gullerya.sqldsl.api.statements.Insert; -import com.gullerya.sqldsl.api.statements.Select; -import com.gullerya.sqldsl.api.statements.Update; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EntityDALImpl implements EntityDAL { + private static final Logger logger = LoggerFactory.getLogger(EntityDALImpl.class); private final ESConfig config; public EntityDALImpl(Class entityType, DataSource ds) throws ReflectiveOperationException { @@ -30,8 +29,8 @@ public int deleteAll() { } @Override - public int deleteAll(Where.WhereClause whereClause) { - return new StatementDeleteImpl<>(config).deleteAll(whereClause); + public int delete(Where.WhereClause whereClause) { + return new StatementDeleteImpl<>(config).delete(whereClause); } @Override @@ -61,6 +60,9 @@ public UpdateDownstream update(T entity, Literal... literals) { record ESConfig(DataSource ds, EntityMetaProc em) { R prepareStatementAndDo(String sql, PreparedStatementAction psAction) { + if (logger.isDebugEnabled()) { + logger.debug(sql); + } try (Connection c = ds.getConnection(); PreparedStatement s = c.prepareStatement(sql)) { return psAction.execute(s); } catch (SQLException sqle) { diff --git a/src/main/java/com/gullerya/sqldsl/impl/StatementDeleteImpl.java b/src/main/java/com/gullerya/sqldsl/impl/StatementDeleteImpl.java index 4ae3971..67e59fa 100644 --- a/src/main/java/com/gullerya/sqldsl/impl/StatementDeleteImpl.java +++ b/src/main/java/com/gullerya/sqldsl/impl/StatementDeleteImpl.java @@ -14,7 +14,7 @@ public int deleteAll() { } @Override - public int deleteAll(Where.WhereClause where) { + public int delete(Where.WhereClause where) { validateWhereClause(config.em(), where); return internalDelete(where); } @@ -30,8 +30,8 @@ private int internalDelete(Where.WhereClause where) { int i = 0; for (Where.WhereFieldValuePair parameter : parametersCollector) { i++; - FieldMetaProc fm = config.em().byColumn.get(parameter.column); - Object pv = fm.translateFieldToColumn(parameter.value); + FieldMetaProc fm = config.em().byColumn.get(parameter.column()); + Object pv = fm.translateFieldToColumn(parameter.value()); s.setObject(i, pv); } } diff --git a/src/main/java/com/gullerya/sqldsl/impl/StatementSelectImpl.java b/src/main/java/com/gullerya/sqldsl/impl/StatementSelectImpl.java index d0250c3..8a979c9 100644 --- a/src/main/java/com/gullerya/sqldsl/impl/StatementSelectImpl.java +++ b/src/main/java/com/gullerya/sqldsl/impl/StatementSelectImpl.java @@ -118,7 +118,7 @@ public List readAll() { } @Override - public List readAll(int limit) { + public List read(int limit) { if (limit == 0) { throw new IllegalArgumentException("limit MUST be greater than 0"); } @@ -126,7 +126,7 @@ public List readAll(int limit) { } @Override - public List readAll(int offset, int limit) { + public List read(int offset, int limit) { if (offset == 0) { throw new IllegalArgumentException("offset MUST be greater than 0 ('read' methods without offset exists)"); } @@ -160,8 +160,8 @@ private List internalRead(Integer offset, Integer limit) { int i = 0; for (WhereFieldValuePair parameter : parametersCollector) { i++; - FieldMetaProc fm = config.em().byColumn.get(parameter.column); - Object pv = fm.translateFieldToColumn(parameter.value); + FieldMetaProc fm = config.em().byColumn.get(parameter.column()); + Object pv = fm.translateFieldToColumn(parameter.value()); s.setObject(i, pv); } try (ResultSet rs = s.executeQuery()) { diff --git a/src/main/java/com/gullerya/sqldsl/impl/StatementUpdateImpl.java b/src/main/java/com/gullerya/sqldsl/impl/StatementUpdateImpl.java index 6389b01..b5ceb15 100644 --- a/src/main/java/com/gullerya/sqldsl/impl/StatementUpdateImpl.java +++ b/src/main/java/com/gullerya/sqldsl/impl/StatementUpdateImpl.java @@ -103,8 +103,8 @@ private int internalUpdate(WhereClause where) { } if (where != null) { for (Where.WhereFieldValuePair parameter : parametersCollector) { - FieldMetaProc fm = config.em().byColumn.get(parameter.column); - fm.setColumnValue(s, ++i, parameter.value); + FieldMetaProc fm = config.em().byColumn.get(parameter.column()); + fm.setColumnValue(s, ++i, parameter.value()); } } return s.executeUpdate(); diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e6f3258..05a1c33 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,8 +1,8 @@ module com.gullerya.sqldsl { requires java.persistence; requires java.sql; + requires org.slf4j; exports com.gullerya.sqldsl; exports com.gullerya.sqldsl.api.clauses; - exports com.gullerya.sqldsl.api.statements; } diff --git a/src/test/java/com/gullerya/sqldsl/statements/JoinTest.java b/src/test/java/com/gullerya/sqldsl/statements/JoinTest.java new file mode 100644 index 0000000..dd13b7c --- /dev/null +++ b/src/test/java/com/gullerya/sqldsl/statements/JoinTest.java @@ -0,0 +1,75 @@ +package com.gullerya.sqldsl.statements; + +import com.gullerya.sqldsl.DBUtils; +import com.gullerya.sqldsl.Join; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import javax.persistence.*; +import javax.sql.DataSource; +import java.time.LocalDate; +import java.util.*; + + +public class JoinTest { + private static final String TABLE_NAME_A = "JoinTestTableA"; + private static final String TABLE_NAME_B = "JoinTestTableB"; + private static final String TABLE_NAME_C = "JoinTestTableC"; + private static final DataSource dataSource = DBUtils.getDataSource(); + + @BeforeAll + public static void prepare() throws Exception { + for (String tableName : Arrays.asList(TABLE_NAME_A, TABLE_NAME_B, TABLE_NAME_C)) { + dataSource.getConnection() + .prepareStatement( + "DROP TABLE IF EXISTS \"" + tableName + "\";" + + "CREATE TABLE \"" + tableName + "\" (" + + "id BIGINT," + + "state INT," + + "ready BOOLEAN," + + "first_name VARCHAR(128)," + + "last_name VARCHAR(128)," + + "birthday DATE," + + "created TIMESTAMP NOT NULL DEFAULT TIMEZONE('UTC', CURRENT_TIMESTAMP)," + + "updated TIMESTAMP," + + "locales VARCHAR(128)" + + ");" + ) + .execute(); + } + } + + @Test + public void basicE2EInner() { + Join.inner(); + } + + @Test + public void basicE2ETowards() { + Join.toward(); + } + + @Entity + @Table(name = TABLE_NAME_A) + public static final class User { + + @Column(updatable = false, nullable = false) + public long id; + @Column(name = "first_name") + public String firstName; + @Column(name = "last_name") + public String lastName; + @Column + public LocalDate birthday; + + public User() { + } + + User(Long id, String firstName, String lastName, LocalDate birthday) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.birthday = birthday; + } + } +} diff --git a/src/test/java/com/gullerya/sqldsl/entities/SelectTest.java b/src/test/java/com/gullerya/sqldsl/statements/SelectTest.java similarity index 98% rename from src/test/java/com/gullerya/sqldsl/entities/SelectTest.java rename to src/test/java/com/gullerya/sqldsl/statements/SelectTest.java index 0afc11f..903bba1 100644 --- a/src/test/java/com/gullerya/sqldsl/entities/SelectTest.java +++ b/src/test/java/com/gullerya/sqldsl/statements/SelectTest.java @@ -1,4 +1,4 @@ -package com.gullerya.sqldsl.entities; +package com.gullerya.sqldsl.statements; import com.gullerya.sqldsl.DBUtils; import com.gullerya.sqldsl.EntityDAL; @@ -153,7 +153,7 @@ public void testReadManyWithLimitNoOffset() { .select("id", "state", "first_name", "last_name", "birthday") .where(not(eq("state", 3))) .orderBy(OrderBy.asc("first_name")) - .readAll(2); + .read(2); assertNotNull(users); assertEquals(2, users.size()); @@ -191,7 +191,7 @@ public void testReadManyWithOffsetNoLimit() { .select("id", "ready", "first_name", "last_name", "birthday", "locales") .where(or(eq("ready", true), notEq("first_name", "Jim"))) .orderBy(OrderBy.desc("last_name")) - .readAll(2, Integer.MAX_VALUE); + .read(2, Integer.MAX_VALUE); assertNotNull(users); assertEquals(4, users.size()); @@ -246,7 +246,7 @@ public void testReadManyWithLimitOffset() { .select("id", "state", "first_name", "last_name", "birthday", "locales") .where(in("id", Arrays.asList(6001, 6003, 6004, 6007))) .orderBy(OrderBy.asc("state"), OrderBy.desc("last_name")) - .readAll(1, 2); + .read(1, 2); EntityDAL.of(User.class, dataSource).deleteAll(); @@ -390,7 +390,7 @@ public void negativeJ2() { public void negativeK1() { assertThrows( IllegalArgumentException.class, - () -> EntityDAL.of(User.class, dataSource).select("id").where(eq("id", 9999)).readAll(0) + () -> EntityDAL.of(User.class, dataSource).select("id").where(eq("id", 9999)).read(0) ); } @@ -398,7 +398,7 @@ public void negativeK1() { public void negativeK2() { assertThrows( IllegalArgumentException.class, - () -> EntityDAL.of(User.class, dataSource).select("id").where(eq("id", 9999)).readAll(0, 1) + () -> EntityDAL.of(User.class, dataSource).select("id").where(eq("id", 9999)).read(0, 1) ); } @@ -406,7 +406,7 @@ public void negativeK2() { public void negativeK3() { assertThrows( IllegalArgumentException.class, - () -> EntityDAL.of(User.class, dataSource).select("id").where(eq("id", 9999)).readAll(1, 0) + () -> EntityDAL.of(User.class, dataSource).select("id").where(eq("id", 9999)).read(1, 0) ); } diff --git a/src/test/java/com/gullerya/sqldsl/entities/UpdateTest.java b/src/test/java/com/gullerya/sqldsl/statements/UpdateTest.java similarity index 99% rename from src/test/java/com/gullerya/sqldsl/entities/UpdateTest.java rename to src/test/java/com/gullerya/sqldsl/statements/UpdateTest.java index 5c50b8f..8f9989c 100644 --- a/src/test/java/com/gullerya/sqldsl/entities/UpdateTest.java +++ b/src/test/java/com/gullerya/sqldsl/statements/UpdateTest.java @@ -1,4 +1,4 @@ -package com.gullerya.sqldsl.entities; +package com.gullerya.sqldsl.statements; import com.gullerya.sqldsl.DBUtils; import com.gullerya.sqldsl.EntityDAL; diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml new file mode 100644 index 0000000..b9cb8d9 --- /dev/null +++ b/src/test/resources/log4j2.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file