diff --git a/pom.xml b/pom.xml
index 8e42a49..dabea04 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,15 +10,15 @@
4.0.0
- pom
- com.rbkmoney.db.common.lib
+ jar
+
db-common-lib
0.0.1-SNAPSHOT
-
-
UTF-8
+ 3.11.5
+ 0.6.9
@@ -31,4 +31,25 @@
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+ 1.5.10.RELEASE
+ provided
+
+
+ org.jooq
+ jooq
+ ${jooq.version}
+ provided
+
+
+ com.rbkmoney.geck
+ common
+ ${geck.common.version}
+ provided
+
+
+
diff --git a/src/main/java/com/rbkmoney/dao/DaoException.java b/src/main/java/com/rbkmoney/dao/DaoException.java
new file mode 100644
index 0000000..702fc46
--- /dev/null
+++ b/src/main/java/com/rbkmoney/dao/DaoException.java
@@ -0,0 +1,24 @@
+package com.rbkmoney.dao;
+
+public class DaoException extends Exception {
+
+ public DaoException() {
+ }
+
+ public DaoException(String message) {
+ super(message);
+ }
+
+ public DaoException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public DaoException(Throwable cause) {
+ super(cause);
+ }
+
+ public DaoException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/dao/GenericDao.java b/src/main/java/com/rbkmoney/dao/GenericDao.java
new file mode 100644
index 0000000..3284e7e
--- /dev/null
+++ b/src/main/java/com/rbkmoney/dao/GenericDao.java
@@ -0,0 +1,69 @@
+package com.rbkmoney.dao;
+
+import org.jooq.Query;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.core.namedparam.SqlParameterSource;
+import org.springframework.jdbc.support.KeyHolder;
+
+import java.util.List;
+
+public interface GenericDao {
+
+ T fetchOne(Query query, Class type) throws DaoException;
+
+ T fetchOne(Query query, Class type, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ T fetchOne(Query query, RowMapper rowMapper) throws DaoException;
+
+ T fetchOne(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper) throws DaoException;
+
+ T fetchOne(Query query, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ T fetchOne(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ List fetch(Query query, RowMapper rowMapper) throws DaoException;
+
+ List fetch(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper) throws DaoException;
+
+ List fetch(Query query, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ List fetch(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ void executeOne(Query query) throws DaoException;
+
+ void executeOne(String namedSql, SqlParameterSource parameterSource) throws DaoException;
+
+ void executeOne(Query query, KeyHolder keyHolder) throws DaoException;
+
+ void executeOne(String namedSql, SqlParameterSource parameterSource, KeyHolder keyHolder) throws DaoException;
+
+ int execute(Query query) throws DaoException;
+
+ int execute(Query query, int expectedRowsAffected) throws DaoException;
+
+ int execute(Query query, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ int execute(String namedSql) throws DaoException;
+
+ int execute(String namedSql, SqlParameterSource parameterSource) throws DaoException;
+
+ int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected) throws DaoException;
+
+ int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException;
+
+ int execute(Query query, KeyHolder keyHolder) throws DaoException;
+
+ int execute(Query query, int expectedRowsAffected, KeyHolder keyHolder) throws DaoException;
+
+ int execute(Query query, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate, KeyHolder keyHolder) throws DaoException;
+
+ int execute(String namedSql, KeyHolder keyHolder) throws DaoException;
+
+ int execute(String namedSql, SqlParameterSource parameterSource, KeyHolder keyHolder) throws DaoException;
+
+ int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected, KeyHolder keyHolder) throws DaoException;
+
+ int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate, KeyHolder keyHolder) throws DaoException;
+
+}
diff --git a/src/main/java/com/rbkmoney/dao/impl/AbstractGenericDao.java b/src/main/java/com/rbkmoney/dao/impl/AbstractGenericDao.java
new file mode 100644
index 0000000..4ea99c3
--- /dev/null
+++ b/src/main/java/com/rbkmoney/dao/impl/AbstractGenericDao.java
@@ -0,0 +1,247 @@
+package com.rbkmoney.dao.impl;
+
+import com.rbkmoney.dao.DaoException;
+import com.rbkmoney.dao.GenericDao;
+import org.jooq.*;
+import org.jooq.conf.ParamType;
+import org.jooq.impl.DSL;
+import org.jooq.impl.DefaultConfiguration;
+import org.springframework.core.NestedRuntimeException;
+import org.springframework.dao.EmptyResultDataAccessException;
+import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.SingleColumnRowMapper;
+import org.springframework.jdbc.core.namedparam.*;
+import org.springframework.jdbc.support.KeyHolder;
+
+import javax.sql.DataSource;
+import java.sql.Types;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public abstract class AbstractGenericDao extends NamedParameterJdbcDaoSupport implements GenericDao {
+
+ private final DSLContext dslContext;
+
+ public AbstractGenericDao(DataSource dataSource) {
+ setDataSource(dataSource);
+ Configuration configuration = new DefaultConfiguration();
+ configuration.set(SQLDialect.POSTGRES);
+ this.dslContext = DSL.using(configuration);
+ }
+
+ protected DSLContext getDslContext() {
+ return dslContext;
+ }
+
+ @Override
+ public T fetchOne(Query query, Class type) throws DaoException {
+ return fetchOne(query, type, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public T fetchOne(Query query, Class type, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ return fetchOne(query, new SingleColumnRowMapper<>(type), namedParameterJdbcTemplate);
+ }
+
+ @Override
+ public T fetchOne(Query query, RowMapper rowMapper) throws DaoException {
+ return fetchOne(query, rowMapper, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public T fetchOne(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper) throws DaoException {
+ return fetchOne(namedSql, parameterSource, rowMapper, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public T fetchOne(Query query, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ return fetchOne(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), rowMapper, namedParameterJdbcTemplate);
+ }
+
+ @Override
+ public T fetchOne(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ try {
+ return namedParameterJdbcTemplate.queryForObject(
+ namedSql,
+ parameterSource,
+ rowMapper
+ );
+ } catch (EmptyResultDataAccessException ex) {
+ return null;
+ } catch (NestedRuntimeException ex) {
+ throw new DaoException(ex);
+ }
+ }
+
+ @Override
+ public List fetch(Query query, RowMapper rowMapper) throws DaoException {
+ return fetch(query, rowMapper, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public List fetch(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper) throws DaoException {
+ return fetch(namedSql, parameterSource, rowMapper, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public List fetch(Query query, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ return fetch(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), rowMapper, namedParameterJdbcTemplate);
+ }
+
+ @Override
+ public List fetch(String namedSql, SqlParameterSource parameterSource, RowMapper rowMapper, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ try {
+ return namedParameterJdbcTemplate.query(
+ namedSql,
+ parameterSource,
+ rowMapper
+ );
+ } catch (NestedRuntimeException e) {
+ throw new DaoException(e);
+ }
+ }
+
+ @Override
+ public void executeOne(Query query) throws DaoException {
+ execute(query, 1);
+ }
+
+ @Override
+ public void executeOne(String namedSql, SqlParameterSource parameterSource) throws DaoException {
+ execute(namedSql, parameterSource, 1);
+ }
+
+ @Override
+ public void executeOne(Query query, KeyHolder keyHolder) throws DaoException {
+ executeOne(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), keyHolder);
+ }
+
+ @Override
+ public void executeOne(String namedSql, SqlParameterSource parameterSource, KeyHolder keyHolder) throws DaoException {
+ execute(namedSql, parameterSource, 1, keyHolder);
+ }
+
+ @Override
+ public int execute(Query query) throws DaoException {
+ return execute(query, -1);
+ }
+
+ @Override
+ public int execute(Query query, int expectedRowsAffected) throws DaoException {
+ return execute(query, expectedRowsAffected, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public int execute(Query query, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ return execute(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), expectedRowsAffected, namedParameterJdbcTemplate);
+ }
+
+ @Override
+ public int execute(String namedSql) throws DaoException {
+ return execute(namedSql, EmptySqlParameterSource.INSTANCE);
+ }
+
+ @Override
+ public int execute(String namedSql, SqlParameterSource parameterSource) throws DaoException {
+ return execute(namedSql, parameterSource, -1);
+ }
+
+ @Override
+ public int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected) throws DaoException {
+ return execute(namedSql, parameterSource, expectedRowsAffected, getNamedParameterJdbcTemplate());
+ }
+
+ @Override
+ public int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate) throws DaoException {
+ try {
+ int rowsAffected = namedParameterJdbcTemplate.update(
+ namedSql,
+ parameterSource);
+
+ if (expectedRowsAffected != -1 && rowsAffected != expectedRowsAffected) {
+ throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(namedSql, expectedRowsAffected, rowsAffected);
+ }
+ return rowsAffected;
+ } catch (NestedRuntimeException ex) {
+ throw new DaoException(ex);
+ }
+ }
+
+ @Override
+ public int execute(Query query, KeyHolder keyHolder) throws DaoException {
+ return execute(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), -1, keyHolder);
+ }
+
+ @Override
+ public int execute(Query query, int expectedRowsAffected, KeyHolder keyHolder) throws DaoException {
+ return execute(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), expectedRowsAffected, getNamedParameterJdbcTemplate(), keyHolder);
+ }
+
+ @Override
+ public int execute(Query query, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate, KeyHolder keyHolder) throws DaoException {
+ return execute(query.getSQL(ParamType.NAMED), toSqlParameterSource(query.getParams()), expectedRowsAffected, namedParameterJdbcTemplate, keyHolder);
+ }
+
+ @Override
+ public int execute(String namedSql, KeyHolder keyHolder) throws DaoException {
+ return execute(namedSql, EmptySqlParameterSource.INSTANCE, keyHolder);
+ }
+
+ @Override
+ public int execute(String namedSql, SqlParameterSource parameterSource, KeyHolder keyHolder) throws DaoException {
+ return execute(namedSql, parameterSource, -1, keyHolder);
+ }
+
+ @Override
+ public int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected, KeyHolder keyHolder) throws DaoException {
+ return execute(namedSql, parameterSource, expectedRowsAffected, getNamedParameterJdbcTemplate(), keyHolder);
+ }
+
+ @Override
+ public int execute(String namedSql, SqlParameterSource parameterSource, int expectedRowsAffected, NamedParameterJdbcTemplate namedParameterJdbcTemplate, KeyHolder keyHolder) throws DaoException {
+ try {
+ int rowsAffected = namedParameterJdbcTemplate.update(
+ namedSql,
+ parameterSource,
+ keyHolder);
+
+ if (expectedRowsAffected != -1 && rowsAffected != expectedRowsAffected) {
+ throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(namedSql, expectedRowsAffected, rowsAffected);
+ }
+ return rowsAffected;
+ } catch (NestedRuntimeException ex) {
+ throw new DaoException(ex);
+ }
+ }
+
+ protected Condition appendDateTimeRangeConditions(Condition condition,
+ Field field,
+ Optional fromTime,
+ Optional toTime) {
+ if (fromTime.isPresent()) {
+ condition = condition.and(field.ge(fromTime.get()));
+ }
+
+ if (toTime.isPresent()) {
+ condition = condition.and(field.lt(toTime.get()));
+ }
+ return condition;
+ }
+
+ protected SqlParameterSource toSqlParameterSource(Map> params) {
+ MapSqlParameterSource sqlParameterSource = new MapSqlParameterSource();
+ for (Map.Entry> entry : params.entrySet()) {
+ Param> param = entry.getValue();
+ if (param.getValue() instanceof LocalDateTime || param.getValue() instanceof EnumType) {
+ sqlParameterSource.addValue(entry.getKey(), param.getValue(), Types.OTHER);
+ } else {
+ sqlParameterSource.addValue(entry.getKey(), param.getValue());
+ }
+ }
+ return sqlParameterSource;
+ }
+
+}
diff --git a/src/main/java/com/rbkmoney/mapper/RecordRowMapper.java b/src/main/java/com/rbkmoney/mapper/RecordRowMapper.java
new file mode 100644
index 0000000..913b746
--- /dev/null
+++ b/src/main/java/com/rbkmoney/mapper/RecordRowMapper.java
@@ -0,0 +1,52 @@
+package com.rbkmoney.mapper;
+
+import com.rbkmoney.geck.common.util.TypeUtil;
+import org.jooq.Field;
+import org.jooq.Table;
+import org.jooq.TableRecord;
+import org.jooq.impl.TableRecordImpl;
+import org.springframework.jdbc.core.RowMapper;
+
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+public class RecordRowMapper implements RowMapper {
+
+ private final Table table;
+
+ private final Class type;
+
+ public RecordRowMapper(Table table, Class type) {
+ this.table = table;
+ this.type = type;
+ }
+
+ @Override
+ public T mapRow(ResultSet resultSet, int i) throws SQLException {
+ ResultSetMetaData rsMetaData = resultSet.getMetaData();
+ int columnCount = rsMetaData.getColumnCount();
+
+ TableRecord record = new TableRecordImpl(table);
+ for (int column = 1; column <= columnCount; column++) {
+ String columnName = rsMetaData.getColumnName(column);
+ Field field = record.field(columnName);
+
+ Object value = getFieldValue(field, resultSet);
+ if (!resultSet.wasNull()) {
+ record.set(field, value);
+ }
+ }
+ return record.into(type);
+ }
+
+ private Object getFieldValue(Field field, ResultSet resultSet) throws SQLException {
+ if (field.getDataType().isBinary()) {
+ return resultSet.getBytes(field.getName());
+ }
+ if (field.getType().isEnum()) {
+ return TypeUtil.toEnumField(resultSet.getString(field.getName()), field.getType());
+ }
+ return resultSet.getObject(field.getName(), field.getType());
+ }
+}