diff --git a/pom.xml b/pom.xml index 185ebca6..1aabb0e6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ sorm4j-parent sorm4j-parent Simple micro Object-Relation Mapper for Java - 1.4.15 + 1.4.16 pom https://github.com/yuu-nkjm/sorm4j @@ -29,7 +29,6 @@ ${project.version} - 1.4.15 UTF-8 diff --git a/sorm4j-example/pom.xml b/sorm4j-example/pom.xml index 830c13c4..1dbb315c 100644 --- a/sorm4j-example/pom.xml +++ b/sorm4j-example/pom.xml @@ -2,11 +2,11 @@ 4.0.0 org.nkjmlab sorm4j-example - 1.4.13 + 1.4.16 Example of Sorm4j - 1.4.15 + 1.4.16 UTF-8 -Xdoclint:none true @@ -24,13 +24,13 @@ com.h2database h2 - 1.4.200 + 2.1.214 org.apache.logging.log4j log4j-core - 2.17.1 + 2.20.0 diff --git a/sorm4j-jmh/pom.xml b/sorm4j-jmh/pom.xml index 798ab1f4..b613e5ab 100644 --- a/sorm4j-jmh/pom.xml +++ b/sorm4j-jmh/pom.xml @@ -26,7 +26,7 @@ Sorm4j benchmark - 1.4.15 + 1.4.16 UTF-8 diff --git a/sorm4j/pom.xml b/sorm4j/pom.xml index 2ec246c8..d6e89a96 100644 --- a/sorm4j/pom.xml +++ b/sorm4j/pom.xml @@ -7,7 +7,7 @@ org.nkjmlab sorm4j-parent - 1.4.15 + 1.4.16 3.27.0-GA diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/Orm.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/Orm.java index c1e9e56c..4ac70ae4 100644 --- a/sorm4j/src/main/java/org/nkjmlab/sorm4j/Orm.java +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/Orm.java @@ -145,6 +145,13 @@ public interface Orm { */ int[] deleteIn(String tableName, @SuppressWarnings("unchecked") T... objects); + @Experimental + boolean execute(ParameterizedSql sql); + + @Experimental + boolean execute(String sql, Object... parameters); + + /** * Executes the query with the given PreparedStatement and applies the given * {@link ResultSetTraverser}. If you want to set parameters to a PreparedStatement object by diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/OrmConnectionImpl.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/OrmConnectionImpl.java index aee9b284..90b557f3 100644 --- a/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/OrmConnectionImpl.java +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/OrmConnectionImpl.java @@ -204,6 +204,19 @@ private final R execSqlIfParameterExists(T[] objects, return sqlFunction.apply(mapping); } + @Override + public boolean execute(ParameterizedSql sql) { + return execute(sql.getSql(), sql.getParameters()); + + } + + @Override + public boolean execute(String sql, Object... parameters) { + return executeAndClose(getLoggerContext(), getJdbcConnection(), getPreparedStatementSupplier(), + getSqlParametersSetter(), sql, parameters); + } + + @Override public T executeQuery(FunctionHandler statementSupplier, ResultSetTraverser traverser) { @@ -933,6 +946,18 @@ private static R executeQueryAndClose(Connection connection, } } + private static boolean executeAndClose(LoggerContext loggerContext, Connection connection, + PreparedStatementSupplier statementSupplier, SqlParametersSetter sqlParametersSetter, + String sql, Object[] parameters) { + try (PreparedStatement stmt = statementSupplier.prepareStatement(connection, sql)) { + sqlParametersSetter.setParameters(stmt, parameters); + boolean ret = stmt.execute(); + return ret; + } catch (SQLException e) { + throw Try.rethrow(e); + } + } + private static R executeQueryAndClose(LoggerContext loggerContext, Connection connection, PreparedStatementSupplier statementSupplier, SqlParametersSetter sqlParametersSetter, String sql, Object[] parameters, ResultSetTraverser resultSetTraverser) { diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/SormImpl.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/SormImpl.java index 4e7db9ab..0970b557 100644 --- a/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/SormImpl.java +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/internal/SormImpl.java @@ -510,6 +510,16 @@ public TableSql getTableSql(String tableName) { return applyAndClose(conn -> conn.getTableSql(tableName)); } + @Override + public boolean execute(ParameterizedSql sql) { + return applyAndClose(conn -> conn.execute(sql)); + } + + @Override + public boolean execute(String sql, Object... parameters) { + return applyAndClose(conn -> conn.execute(sql, parameters)); + } + @Override public T executeQuery(FunctionHandler statementSupplier, ResultSetTraverser traverser) { diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/BasicRowMap.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/BasicRowMap.java index 1f30330f..93a59a63 100644 --- a/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/BasicRowMap.java +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/BasicRowMap.java @@ -13,9 +13,8 @@ import java.util.function.BiFunction; import java.util.stream.Collectors; import org.nkjmlab.sorm4j.internal.util.ArrayUtils; -import org.nkjmlab.sorm4j.internal.util.StringCache; -public final class BasicRowMap implements RowMap { +public class BasicRowMap implements RowMap { private final LinkedHashMap map; @@ -28,12 +27,12 @@ public BasicRowMap(int initialCapacity, float loadFactor) { } public BasicRowMap(Map map) { - this.map = map.entrySet().stream().collect(Collectors.toMap(en -> toKey(en.getKey()), - en -> en.getValue(), (v1, v2) -> v1, LinkedHashMap::new)); + this.map = List.copyOf(map.entrySet()).stream().collect(LinkedHashMap::new, + (m, v) -> m.put(toKey(v.getKey()), v.getValue()), LinkedHashMap::putAll); } - private static String toKey(Object key) { - return StringCache.toCanonicalCase(key.toString()); + private static String toKey(String key) { + return RowMap.toKey(key); } @Override @@ -48,7 +47,7 @@ public boolean isEmpty() { @Override public boolean containsKey(Object key) { - return map.containsKey(toKey(key)); + return map.containsKey(toKey(key.toString())); } @Override @@ -58,7 +57,7 @@ public boolean containsValue(Object value) { @Override public Object get(Object key) { - return map.get(toKey(key)); + return map.get(toKey(key.toString())); } @Override @@ -68,7 +67,7 @@ public Object put(String key, Object value) { @Override public Object remove(Object key) { - return map.remove(toKey(key)); + return map.remove(toKey(key.toString())); } @Override diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/RowMap.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/RowMap.java index 2888befe..32d34ab7 100644 --- a/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/RowMap.java +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/result/RowMap.java @@ -5,6 +5,8 @@ import java.time.LocalTime; import java.util.List; import java.util.Map; +import org.nkjmlab.sorm4j.annotation.Experimental; +import org.nkjmlab.sorm4j.internal.util.StringCache; /** * A instance represents a row in a table. This interface extends {@link Map}. The @@ -51,6 +53,16 @@ static RowMap of(String k1, Object v1, String k2, Object v2, String k3, Object v return create(Map.of(k1, v1, k2, v2, k3, v3, k4, v4, k5, v5)); } + /** + * Key to canonical key + * + * @param key + * @return + */ + @Experimental + static String toKey(String key) { + return StringCache.toCanonicalCase(key); + } T[] getArray(String key, Class componentType); diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/H2CsvReadSql.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/H2CsvReadSql.java index 3ddd040c..3384ba82 100644 --- a/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/H2CsvReadSql.java +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/H2CsvReadSql.java @@ -17,7 +17,6 @@ import org.nkjmlab.sorm4j.internal.util.ParameterizedStringFormatter; import org.nkjmlab.sorm4j.internal.util.StringCache; import org.nkjmlab.sorm4j.util.table_def.TableDefinition; -import org.nkjmlab.sorm4j.util.table_def.annotation.AutoIncrement; @Experimental public class H2CsvReadSql { @@ -87,7 +86,8 @@ public H2CsvReadSql build() { int index = selectedColumns.indexOf(en.getKey()); if (index == -1) { Object[] params = {en.getKey(), columns}; - throw new IllegalStateException(ParameterizedStringFormatter.LENGTH_256.format("{} is not found in Columns {}", params)); + throw new IllegalStateException(ParameterizedStringFormatter.LENGTH_256 + .format("{} is not found in Columns {}", params)); } selectedColumns.set(index, en.getValue()); }); @@ -164,7 +164,7 @@ public Builder setOrmRecordClass(Class ormRecordClass) { .filter(f -> !java.lang.reflect.Modifier.isStatic(f.getModifiers())) .toArray(Field[]::new); - List autoGeneratedColumn = new ArrayList<>(); + List csvSkipColumns = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; @@ -180,14 +180,16 @@ public Builder setOrmRecordClass(Class ormRecordClass) { if (ann instanceof CsvColumn) { mapCsvColumnToTableColumn(((CsvColumn) ann).value(), StringCache.toUpperSnakeCase(field.getName())); - } else if (ann instanceof AutoIncrement) { - autoGeneratedColumn.add(field); + } else if (ann instanceof SkipCsvRead) { + csvSkipColumns.add(field); } } } - setTableColumns(Stream.of(fields).filter(f -> !autoGeneratedColumn.contains(f)) - .map(f -> StringCache.toUpperSnakeCase(f.getName())).toArray(String[]::new)); + setTableColumns(Stream.of(fields).map(f -> { + return csvSkipColumns.contains(f) ? "null as " + StringCache.toUpperSnakeCase(f.getName()) + : StringCache.toUpperSnakeCase(f.getName()); + }).toArray(String[]::new)); return this; } diff --git a/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/SkipCsvRead.java b/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/SkipCsvRead.java new file mode 100644 index 00000000..65218ac8 --- /dev/null +++ b/sorm4j/src/main/java/org/nkjmlab/sorm4j/util/h2/sql/SkipCsvRead.java @@ -0,0 +1,19 @@ +package org.nkjmlab.sorm4j.util.h2.sql; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * The csvread function of the H2 database skips columns based on their annotations. + * + * @author nkjm + * + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.PARAMETER, ElementType.FIELD}) +public @interface SkipCsvRead { + +}