package marubinotto.piggydb.impl.mapper; import static marubinotto.util.CollectionUtils.list; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import marubinotto.piggydb.model.entity.RawEntity; import marubinotto.piggydb.model.exception.BaseDataObsoleteException; import marubinotto.util.Assert; import marubinotto.util.time.DateTime; import org.apache.commons.lang.ArrayUtils; import org.springframework.jdbc.core.JdbcTemplate; public class EntityTable { // Common columns public static final String COLUMN_CREATION_DATETIME = "creation_datetime"; public static final String COLUMN_CREATOR = "creator"; public static final String COLUMN_UPDATE_DATETIME = "update_datetime"; public static final String COLUMN_UPDATER = "updater"; private String tableName; private String primaryKey; private List<String> allColumns = new ArrayList<String>(); private List<String> properColumns = new ArrayList<String>(); public EntityTable(String tableName, String primaryKey) { Assert.Arg.notNull(tableName, "tableName"); Assert.Arg.notNull(primaryKey, "primaryKey"); this.tableName = tableName; this.primaryKey = primaryKey; this.allColumns.addAll(list( this.primaryKey, COLUMN_CREATION_DATETIME, COLUMN_CREATOR, COLUMN_UPDATE_DATETIME, COLUMN_UPDATER)); } public EntityTable defColumn(String column) { Assert.Arg.notNull(column, "column"); Assert.require( !this.allColumns.contains(column), "!this.allColumns.contains(column)"); this.properColumns.add(column); this.allColumns.add(column); return this; } public List<String> getAllColumns() { return this.allColumns; } public List<String> getProperColumns() { return properColumns; } public String getProperColumnName(int index) { return this.properColumns.get(index); } /** * Responsible for: * - setting the creation time and the update time */ public void insert(RawEntity entity, Object[] values, JdbcTemplate jdbcTemplate) { Assert.Arg.notNull(entity, "entity"); Assert.Arg.notNull(values, "values"); Assert.Arg.notNull(jdbcTemplate, "jdbcTemplate"); Assert.Property.requireNotNull(primaryKey, "primaryKey"); StringBuilder sql1 = new StringBuilder("insert into " + this.tableName + " ("); sql1.append(this.primaryKey); sql1.append(", " + COLUMN_CREATION_DATETIME); sql1.append(", " + COLUMN_CREATOR); sql1.append(", " + COLUMN_UPDATE_DATETIME); StringBuilder sql2 = new StringBuilder(") values (?, ?, ?, ?"); for (String column : this.properColumns) { sql1.append(", " + column); sql2.append(", ?"); } String sql = sql1.toString() + sql2.toString() + ")"; DateTime now = DateTime.getCurrentTime(); Object[] commonFields = new Object[] { entity.getId(), now.toDate(), entity.getCreator(), now.toDate() }; jdbcTemplate.update(sql, ArrayUtils.addAll(commonFields, values)); entity.setCreationDatetime(now); entity.setUpdateDatetime(now); } /** * Responsible for: * - optimistic concurrency control with the last-updated time * - setting the update time * * NOTE: "updateTimestamp = false" will disable optimistic lock */ public void update( RawEntity entity, Object[] values, boolean updateTimestamp, JdbcTemplate jdbcTemplate) throws BaseDataObsoleteException { Assert.Arg.notNull(entity, "entity"); Assert.Arg.notNull(values, "values"); Assert.Arg.notNull(jdbcTemplate, "jdbcTemplate"); Assert.Property.requireNotNull(primaryKey, "primaryKey"); StringBuilder sql = new StringBuilder(); sql.append("update " + this.tableName + " set "); sql.append(COLUMN_UPDATE_DATETIME + " = ?"); sql.append(", " + COLUMN_UPDATER + " = ?"); for (String column : this.properColumns) { sql.append(", " + column + " = ?"); } sql.append(" where " + this.primaryKey + " = ?"); sql.append(" and " + COLUMN_UPDATE_DATETIME + " = ?"); DateTime updateDateTime = updateTimestamp ? DateTime.getCurrentTime() : entity.getUpdateDatetime(); List<Object> params = new ArrayList<Object>(); params.add(updateDateTime.toDate()); params.add(entity.getUpdater()); params.addAll(Arrays.asList(values)); params.add(entity.getId()); params.add(entity.getUpdateDatetime().toDate()); int affected = jdbcTemplate.update(sql.toString(), params.toArray()); if (affected == 0) throw new BaseDataObsoleteException(); entity.setUpdateDatetime(updateDateTime); } public void mapCommonColumns(ResultSet rs, String prefix, RawEntity entity) throws SQLException { Assert.Arg.notNull(rs, "rs"); Assert.Arg.notNull(prefix, "prefix"); Assert.Arg.notNull(entity, "entity"); entity.setId(rs.getLong(prefix + this.primaryKey)); entity.setCreationDatetime(new DateTime( rs.getTimestamp(prefix + COLUMN_CREATION_DATETIME))); entity.setCreator(rs.getString(prefix + COLUMN_CREATOR)); entity.setUpdateDatetime(new DateTime( rs.getTimestamp(prefix + COLUMN_UPDATE_DATETIME))); entity.setUpdater(rs.getString(prefix + COLUMN_UPDATER)); } }