S2JDBC をちょっといじってみました。
S2JDBCを調査していていて、以下の1点だけできないことがあったので自分で実装してみました。
「できないこと」とは、テーブルのUpdateTime等のカラムを getdate()関数の値で UpdateやInsertを実行することが SQLの自動生成ではできないことです。多少わがままな願いかもしれませんが、そのためだけに SQLの自動生成を捨てて SQLファイルを作るのが嫌だったので、自動生成のクラスをオーバーライドして、自前実装を作ってみました。
色々と突っ込みどころ満載だと思いますので、どんどん突っ込みよろしくです。
AutoUpdateSetGetdateImpl.java
package org.seasar.extension.jdbc.extend; import java.util.List; import java.util.Set; import org.seasar.extension.jdbc.AutoUpdate; import org.seasar.extension.jdbc.PropertyMeta; import org.seasar.extension.jdbc.manager.JdbcManagerImplementor; import org.seasar.extension.jdbc.query.AutoUpdateImpl; import org.seasar.framework.util.tiger.CollectionsUtil; /** * <p>AutoUpdateExtendedImpl</p> */ public class AutoUpdateSetGetdateImpl<T> extends AutoUpdateImpl<T> implements AutoUpdate<T> { protected final Set<String> getdateColumnSet_ = CollectionsUtil.newHashSet(); /** * AutoUpdateExtendedImpl * @param jdbcManager * @param entity * @param columns */ public AutoUpdateSetGetdateImpl(JdbcManagerImplementor jdbcManager, T entity, String... columns) { super(jdbcManager, entity); for (final String column: columns) { getdateColumnSet_.add(column); } } @Override protected void prepareSetClause() { List<PropertyMeta> removeList = CollectionsUtil.newArrayList(); for (final PropertyMeta propertyMeta : targetProperties) { if (getdateColumnSet_.contains(propertyMeta.getField().getName())) { setClause.addSql(propertyMeta.getColumnMeta().getName(), "getdate()"); removeList.add(propertyMeta); } else { setClause.addSql(propertyMeta.getColumnMeta().getName()); } } if (!includeVersion && entityMeta.hasVersionPropertyMeta()) { final PropertyMeta propertyMeta = entityMeta.getVersionPropertyMeta(); final String columnName = propertyMeta.getColumnMeta().getName(); setClause.addSql(columnName, columnName + " + 1"); } for (final PropertyMeta propertyMeta : removeList) { targetProperties.remove(propertyMeta); } } }
AutoInsertSetGetdateImpl.java
package org.seasar.extension.jdbc.extend; import java.util.List; import java.util.Set; import org.seasar.extension.jdbc.AutoInsert; import org.seasar.extension.jdbc.PropertyMeta; import org.seasar.extension.jdbc.manager.JdbcManagerImplementor; import org.seasar.extension.jdbc.query.AutoInsertImpl; import org.seasar.framework.util.tiger.CollectionsUtil; /** * <p>AutoInsertSetGetdateImpl</p> */ public class AutoInsertSetGetdateImpl<T> extends AutoInsertImpl<T> implements AutoInsert<T> { protected final Set<String> getdateColumnSet_ = CollectionsUtil.newHashSet(); /** * AutoInsertSetGetdateImpl * @param jdbcManager * @param entity * @param columns */ public AutoInsertSetGetdateImpl(JdbcManagerImplementor jdbcManager, T entity, String... columns) { super(jdbcManager, entity); for (final String column: columns) { getdateColumnSet_.add(column); } } @Override protected void prepareValuesClause() { List<PropertyMeta> removeList = CollectionsUtil.newArrayList(); for (final PropertyMeta propertyMeta : targetProperties) { if (getdateColumnSet_.contains(propertyMeta.getField().getName())) { valuesClause.addSql("getdate()"); removeList.add(propertyMeta); } else { valuesClause.addSql(); } } for (final PropertyMeta propertyMeta : removeList) { targetProperties.remove(propertyMeta); } } }
JdbcManagerSetGetdateImpl.java
package org.seasar.extension.jdbc.extend; import org.seasar.extension.jdbc.AutoInsert; import org.seasar.extension.jdbc.AutoUpdate; import org.seasar.extension.jdbc.EntityMeta; import org.seasar.extension.jdbc.JdbcManager; import org.seasar.extension.jdbc.exception.NoIdPropertyRuntimeException; import org.seasar.extension.jdbc.manager.JdbcManagerImpl; import org.seasar.extension.jdbc.manager.JdbcManagerImplementor; /** * <p>JdbcManagerSetGetdateImpl</p> */ public class JdbcManagerSetGetdateImpl extends JdbcManagerImpl implements JdbcManager, JdbcManagerImplementor { private static final String[] GETDATE_COLUMNS = new String[] {"updateTime", "createTime"}; /** * JdbcManagerSetGetdateImpl */ public JdbcManagerSetGetdateImpl() { } @Override public <T> AutoInsert<T> insert(final T entity) { return new AutoInsertSetGetdateImpl<T>(this, entity, GETDATE_COLUMNS).queryTimeout(queryTimeout); } @Override public <T> AutoUpdate<T> update(final T entity) { final EntityMeta entityMeta = entityMetaFactory.getEntityMeta(entity.getClass()); if (entityMeta.getIdPropertyMetaList().isEmpty()) { throw new NoIdPropertyRuntimeException("ESSR0761", entityMeta.getName()); } return new AutoUpdateSetGetdateImpl<T>(this, entity, GETDATE_COLUMNS).queryTimeout(queryTimeout); } }
以上の3ファイルを作った後に、s2jdbc.dicon をこっちのJDBCManagerを使うように変更します。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN" "http://www.seasar.org/dtd/components24.dtd"> <components> <include path="jdbc.dicon"/> <include path="s2jdbc-internal.dicon"/> <component name="jdbcManager" class="org.seasar.extension.jdbc.extend.JdbcManagerSetGetdateImpl"> <property name="maxRows">0</property> <property name="fetchSize">0</property> <property name="queryTimeout">0</property> <property name="dialect">hsqlDialect</property> </component> </components>
以上で、以下のようなコードを実行すると、Entityの updateTimeと createTimeのフィールドが getdate()で更新されるようになります。
package jp.ifp.xdss.manager.entity; import java.sql.Timestamp; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Entity { @Id @GeneratedValue public int id; public String name; public String note; public Timestamp updateTime; @Column(updatable = false) public Timestamp createTime; }
import org.seasar.extension.jdbc.JdbcManager; import org.seasar.extension.jdbc.where.SimpleWhere; import org.seasar.extension.unit.S2TestCase; public class UpdateEntityTest extends S2TestCase { private JdbcManager jdbcManager; @Override protected void setUp() throws Exception { include("app.dicon"); } public void testUpdateTx() throws Exception { Entity entity = new Entity(); entity.name = "Insert"; jdbcManager.insert(entity).execute(); entity.name = "Updated"; jdbcManager.update(entity).execute(); } }