MyBatis × Oracleでハマる “Invalid column type: 1111” エラーの原因と対策
はじめに
Spring Boot × MyBatis × Oracle の構成で開発していると、INSERTやUPDATE時に突然こんなエラーが出ることがあります。
java.sql.SQLException: Invalid column type: 1111
アプリケーションログを見ると、MyBatisSystemException が発生し、SQL実行部分で止まっています。
本記事では、このエラーの正体と、どう直せば良いかを具体的なコード例で解説します。
エラーの原因
Oracleで Invalid column type: 1111 が出るのは、JDBCの Types.OTHER (1111) が setNull() に渡されるためです。
MyBatisは、パラメータが null の場合、デフォルトで jdbcType=OTHER として扱います。
しかしOracleドライバは Types.OTHER をサポートしていないため、Invalid column type: 1111 という例外を投げます。
💥 エラーが起きる従来のコード
たとえば、次のようなマッパーを考えてみましょう。
<!-- NG例: jdbcType未指定 -->
<insert id="insertUser" parameterType="User">
INSERT INTO USERS (ID, NAME, AGE, NOTE)
VALUES (#{id}, #{name}, #{age}, #{note})
</insert>
Java側で以下のように null を渡すと……
User user = new User();
user.setId(1);
user.setName("Suzuki");
user.setAge(null); // ← nullを設定
user.setNote(null); // ← nullを設定
userMapper.insertUser(user);
これがOracleでは Invalid column type: 1111 で落ちます。
MyBatisが PreparedStatement.setNull(parameterIndex, Types.OTHER) を呼び出すためです。
✅修正版①: jdbcType を明示的に指定する
最も確実な方法は、MyBatisマッパーで jdbcType を明示的に設定することです。
<!-- OK例: jdbcTypeを明示 -->
<insert id="insertUser" parameterType="User">
INSERT INTO USERS (ID, NAME, AGE, NOTE)
VALUES (
#{id,jdbcType=NUMBER},
#{name,jdbcType=VARCHAR},
#{age,jdbcType=NUMBER},
#{note,jdbcType=VARCHAR}
)
</insert>
これでMyBatisは、null の場合でも適切な型 (setNull(index, java.sql.Types.NUMBER) など) でOracleに値を送ります。
結果、Invalid column type: 1111 は発生しません。
✅修正版②: MyBatisの設定でデフォルトを変更する
もし毎回 jdbcType を書くのが面倒な場合は、mybatis-config.xml に次の設定を追加します。
<settings>
<setting name="jdbcTypeForNull" value="NULL"/>
</settings>
これにより、MyBatisが内部的に Types.OTHER ではなく Types.NULL を使用します。
シンプルな対応ですが、プロジェクト全体に影響するため慎重に導入してください。
✅修正版③: 動的SQLで null カラムをスキップ
null をDBに入れたくない場合は、動的SQLを使って該当列をスキップするのも有効です。
<insert id="insertUser" parameterType="User">
INSERT INTO USERS
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">ID,</if>
<if test="name != null">NAME,</if>
<if test="age != null">AGE,</if>
<if test="note != null">NOTE,</if>
</trim>
<trim prefix="VALUES (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="name != null">#{name},</if>
<if test="age != null">#{age},</if>
<if test="note != null">#{note},</if>
</trim>
</insert>
これにより、null の項目をSQLに含めず安全にINSERTできます。
🧠 まとめ
- MyBatisはnullを扱う際、デフォルトでTypes.OTHERを使う
- Oracleはこれを受け付けず、Invalid column type: 1111が発生する
- 対策は以下のいずれか:
- jdbcType を明示する(推奨)
- mybatis-config.xml で jdbcTypeForNull=NULL を設定
- 動的SQLで null カラムをスキップする
- 対策は以下のいずれか:
💬 おわりに
本エラーは一見「Oracle側の問題」に見えますが、実際にはMyBatisのJDBC型推定の仕様が原因です。Oracle特有の制約により発生しやすいので、マッパーに jdbcType を書く習慣を付けておくと安全です。
Discussion