[Seasar-user:9903] Re: [DbFlute]entity にidentityの値が設定されない

Koichi Kobayashi [E-MAIL ADDRESS DELETED]
2007年 8月 15日 (水) 01:00:06 JST


小林 (koichik) です.

Date:    Tue, 14 Aug 2007 22:16:46 +0900
From:    kubo <[E-MAIL ADDRESS DELETED]>
To:      [E-MAIL ADDRESS DELETED]
Subject: [Seasar-user:9901] Re: [DbFlute]entity にidentityの値が設定されない

> トランザクションなし
>   → Insert後にEntityにIDが設定されない。★
>   → 自分で明示的に「select @@identity」で値が取得できた。
> 
> 自分で明示的に取得した場合に両方共正常に取得できること
> 裏返すとトランザクションなしのときにS2Daoの発行する
> 「select @@identity」で値が取得できないこと
> が、不思議です。

ログからは分かりにくいですが,S2Dao は
insert とその後の select @@identity を
別の (論理) コネクションで実行します.

insert は InsertAutoHandler とその
スーパークラス AbstractAutoHandler の

    public int execute(Object[] args) throws SQLRuntimeException {
        Connection connection = getConnection();
        try {
            return execute(connection, args[0]);
        } finally {
            ConnectionUtil.close(connection);
        }
    }

で実行されますが,ここで取得された
コネクションは execute(Connection, Object) が
終了するまでクローズされません.ここポイント.

そして execute(Connection, Object) の中から
呼び出される

    protected void preUpdateBean(Object bean) {
        IdentifierGenerator generator = getBeanMetaData()
                .getIdentifierGenerator();
        if (generator.isSelfGenerate()) {
            generator.setIdentifier(bean, getDataSource());
        }
    }

から IdentityIdentifierGenerator の

    public void setIdentifier(Object bean, DataSource ds) {
        Object value = executeSql(ds, getDbms().getIdentitySelectString(), null);
        setIdentifier(bean, value);
    }

が呼び出されます.
これは最終的に BasicSelectHandler の

    public Object execute(Object[] args, Class[] argTypes)
            throws SQLRuntimeException {
        Connection con = getConnection();
        try {
            return execute(con, args, argTypes);
        } catch (SQLException ex) {
            throw new SQLRuntimeException(ex);
        } finally {
            ConnectionUtil.close(con);
        }
    }

で実行されます.
ここでもコネクションが取得されていることに注意.

ちゃんとトランザクション制御されていれば,
InsertAutoHandler と BasicSelectHandler が
取得するコネクションは,同じ物理コネクションと
なります.
しかし,トランザクション制御されていない場合,
それぞれのコネクションは別の物理コネクションと
なってしまいます.

insert と select @@identity が別の
物理コネクションで実行されるわけなので,
正しい値が取得できるわけがないことになります.


-- 
<component name="koichik">
    <property name="fullName">"Koichi Kobayashi"</property>
    <property name="email">"[E-MAIL ADDRESS DELETED]"</property>
    <property name="blog">"http://d.hatena.ne.jp/koichik"</property>
</component>




Seasar-user メーリングリストの案内