Hatena::Groupseasarproject

S2できるかな?

2016-09-26

EOL

Seasarプロジェクトが提供するプロダクトの多くは 2016年9月26日 をもって EOL (End of Life) となります。

The Seasar Project

コミッターの方々、お疲れ様でした&ありがとうございました。

Seasar2無かったら、Webアプリケーション/Javaでプログラミング/アジャイルと開発効率、とか無縁だったと思うし、本当に感謝しております。

私も微力ながら、最期にちょっと貢献出来たのが、今となっては良い思い出です。*1


上記の二つがSeasarプロジェクト離れて、開発が継続されることにになったのは、かなり嬉しいことですね。O/Rマッパーと、HTMLテンプレート、と言う超重要なライブラリが生き残った、これだけでも、本当に素晴らしいと思います。*2


で、この3つが生き残れなかったのは、ちょっと残念だったかな…。

Cubbyは、依存が少なく、GuiceやSpringFrameworkにも対応していたし、「ちょっとしたWebアプリ」を作成するのは、相当楽だったんですけどね…。

S2Utilは、Guava/NIO2辺りと被るものもあるんですが、やっぱりBeanUtilが便利過ぎなので。 と言うか、Java9になるのに、Java Beansのコピーさえも、言語レベルでサポートされない、というのは、これどうしたことでしょうね…。

そしてS2Mai。 この前、JavaMail/Guice/FreeMarkerで同じようなもの作ろうとしたら、やっぱ面倒でしたよね。 2016年になっても、テキストベースのemailを送らなければいけない人類なのです。


三年ぶりに日記を更新したら楽しかったです。

*1g:seasarproject:id:halflite:20130307:s2jdbcgen

*2:O/Rマッパーと、HTMLテンプレートは、決定打がないので、バリエーションがいっぱいあったほうがいいと思うのです

トラックバック - http://seasarproject.g.hatena.ne.jp/halflite/20160926

2013-10-21

Seasar 2.4.47 リリース

新しい版がリリースされて、S2JDBC-Genの困っていた問題*1fixされましたね。

コミット件数が可視化されると、2009年以降、ガクッと勢いが無くなるのが丸分かりで切ないですねぇ…。

トラックバック - http://seasarproject.g.hatena.ne.jp/halflite/20131021

2013-03-07

トラックバック - http://seasarproject.g.hatena.ne.jp/halflite/20130307

2013-03-06

JDKによって、S2JDBC-Genで作られるスキーマが違う件

昨日*1の続き。この状態って、

  1. JDK 7を使っている
  2. 基底クラスを作り、それを継承したエンティティクラスを使っている
  3. S2JDBC-Gengen-ddl を実行する

の三つの条件が揃わないと、こう言った困った状況に陥らないので、もしかして、この条件で開発している人、全然いないの…?、と不安に。

自分も、以前は、「DBMySQL Workbench等で変更」→「S2JDBC-Gengen-entity でエンティティを自動作成」って手順だったし、世間一般のS2ベースの開発手順が、そうなんじゃ…、と言う気になってきましたよ。*2

ただしい

  1. エンティティクラスを作成する
  2. AntGen-Ddlを実行しエンティティクラスに対応するCREATE TABLE文を作成する
  3. AntでMigrateを実行しCREATE TABLE文をDBに反映させる

先にエンティティクラスを作成するという点が超重要です。

新しいテーブルの作成 - taediumの日記

*1g:seasarproject:id:halflite:20130305

*2:新規開発と言っても、古いDBをそのまま引き継いで、Webアプリ化、みたいな案件も多いと聞きます。

トラックバック - http://seasarproject.g.hatena.ne.jp/halflite/20130306

2013-03-05

Java SE 6と7では、S2JDBC-Genで作られるDDLのスキーマが違う。#2

g:seasarproject:id:halflite:20120626:s2jdbcgen の続きです。*1 これのために、JDK 7に移行するのを躊躇してたんですが、JDK 6もEoLですし*2、これを機会に、正しく向き合おうかと…。

例えば、こんな二つのクラスで、エンティティを作ります。

/** 更新可能entityの抽象クラス */
@MappedSuperclass
public abstract class AbstractUpdatableEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /** ID */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    /** 変更時間 */
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date modified;

    /** 作成時間 */
    @Column(updatable = false, nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    public Date created;

    @Override
    public String toString() {
        return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}
/** ユーザー変更一時情報 */
@Entity
public class TemporaryUser extends AbstractUpdatableEntity {

	private static final long serialVersionUID = 1L;

	/** ユーザー ID */
	@Column(nullable = false)
	public Long userId;	
	
	/** メールアドレス */
	@Column(length = MAIL_MAX, nullable = false)
	public String mail;

	/** 変更種別 */
	@Column(length = 32, nullable = false)
	@Enumerated(EnumType.STRING)
	public TemporaryUserType type;
	
	@OneToOne
	@ReferentialConstraint(onDelete = ReferentialActionType.CASCADE)
	public User user;

	// -------------------------------------------------- [inner class]

	public static enum TemporaryUserType {
		/** 新規登録時 */
		REGISTERED,
		/** パスワード再発行時 */
		PASSWORD_REISSUED,
		/** メールアドレス変更時 */
		MAIL_CHANGED;
	}
}

S2JDBC-Gengen-ddlでcreate table文を作成。 JDK 6の場合は、以下のSQLが作られます。

create table TEMPORARY_USER (
    ID bigint not null auto_increment comment 'ID',
    USER_ID bigint not null comment 'ユーザー ID',
    MAIL varchar(255) not null comment 'メールアドレス',
    TYPE varchar(32) not null comment '変更種別',
    MODIFIED timestamp not null comment '変更時間',
    CREATED timestamp not null comment '作成時間',
    constraint TEMPORARY_USER_PK primary key(ID)
) comment = 'ユーザー変更一時情報';

しかし、JDK 7で実行した場合の、SQLは以下のようになります。

create table TEMPORARY_USER (
    ID bigint not null auto_increment comment 'ID',
    CREATED timestamp not null comment '作成時間',
    MODIFIED timestamp not null comment '変更時間',
    TYPE varchar(32) not null comment '変更種別',
    MAIL varchar(255) not null comment 'メールアドレス',
    USER_ID bigint not null comment 'ユーザー ID',
    constraint TEMPORARY_USER_PK primary key(ID)
) comment = 'ユーザー変更一時情報';

はい、ID以下のカラムの順番が、丁度逆になってますね…。

別にRDBだから、カラムの並び順とか、オブジェクトにマッピングされてしまえば関係ないのかもしれませんが、これはどうにも座りが悪い…。

Java SE 6と7では、S2JDBC-Genで作られるDDLのスキーマが違う。#3

g:seasarproject:id:halflite:20130305:s2jdbcgen からの続き。

カラムの並び替えは、

org.seasar.extension.jdbc.gen.internal.desc.TableDescFactoryImplクラス

のdoColumnDescメソッドで行っているのですが、そこを

差し替えればできます。

[Seasar-user:17896] Re: S2JDBC-Gen の gen-ddl が生成する DDL での主キーのカラム順について

をヒントに、S2JDBC-Genのソースを落としてきて、Eclipseにインポート、該当のクラスのテストケースを探します。*3

    /**
     * 
     * @throws Exception
     */
    @Test
    public void testColumnDescList_multiClass() throws Exception {
        EntityMeta entityMeta = entityMetaFactory.getEntityMeta(Ggg.class);
        TableDesc tableDesc = tableDescFactory.getTableDesc(entityMeta);
        List<ColumnDesc> list = tableDesc.getColumnDescList();
        assertEquals(6, list.size());
        assertEquals("ID1", list.get(0).getName());
        assertEquals("ID2", list.get(1).getName());
        assertEquals("ID3", list.get(2).getName());
        assertEquals("NAME3", list.get(3).getName());
        assertEquals("NAME2", list.get(4).getName());
        assertEquals("NAME1", list.get(5).getName());
    }

上記テストケース、JDK 6だと通るんですが、JDK 7だと通りません。*4

カラムを並べ替えているComparator実装が原因っぽいです。*5

    /**
     * カラム記述の{@link Comparator}を作成します。
     * 
     * @param tableDesc
     *            テーブル記述
     * @return カラム記述の{@link Comparator}
     */
    protected Comparator<ColumnDesc> createColumnDescComparator(
            TableDesc tableDesc) {
        final List<String> pkColumnNameList = new ArrayList<String>();
        if (tableDesc.getPrimaryKeyDesc() != null) {
            PrimaryKeyDesc primaryKeyDesc = tableDesc.getPrimaryKeyDesc();
            pkColumnNameList.addAll(primaryKeyDesc.getColumnNameList());
        }
        return new Comparator<ColumnDesc>() {

            public int compare(ColumnDesc o1, ColumnDesc o2) {
                int index1 = pkColumnNameList.indexOf(o1.getName());
                int index2 = pkColumnNameList.indexOf(o2.getName());
                int ret = 0;
                if (index1 < 0) {
                    if (index2 < 0) {
                        ret = -1;
                    } else {
                        ret = 1;
                    }
                } else {
                    if (index2 < 0) {
                        ret = -1;
                    } else {
                        ret = index1 - index2;
                    }
                }
                return ret;
            }
        };
    }

ret = ... で定数を返すと、JDK 6/JDK 7でソートのロジック変わったので、それによって、挙動も変わってしまうようです。*6

修正するには、TableDescFactoryImplクラスの、createColumnDescComparatorメソッドを上書きして、JARを作り直せばいいのですが、さて、どう直していいのか分からない…。