MyBatis类型处理程序导致表插入不兼容

时间:2015-10-15 16:38:49

标签: java mybatis typehandler

可能是我误解/误用了MyBatis类型处理程序,但我发现它们可能导致与表插入方法相关的不兼容问题。

考虑课程:

public class TableA {
    int idA;
    String name;
    // constructors, getters, etc.
}

public class TableB {
    int idB;
    TableA objA;
    Date startDate;
    // constructors, getters, etc.
}

我声明了关联表,对于TableB,Id_A是Table_A表行的外键。:

create table Table_A ( int Id_A int auto_increment primary key, name varchar(50) );
create table Table_B ( int Id_B int auto_increment primary key, Id_A int, Start_Date datetime );

我使用方法为TableA,TableAMapper.java声明了一个简单的映射器:

@Insert({ "insert into Table_A ( Id_A, name ) values ( #{idA}, #{name} )" })
@Options(useGeneratedKeys=true, keyProperty="idA")
int insertReturnPK( TableA record );

对于TableBMapper,类型处理程序用于填充TableB.objA,类似的insertReturnPK方法用于objA字段的类型处理程序:

<resultMap id="BaseResultMap" type="TableA">
    <id column="Id_B" jdbcType="INTEGER" property="idB" />
    <result column="Id_A" jdbcType="INTEGER" property="objA" typeHandler="TableATypeHandler" />
    <result column="Start_Date" jdbcType="TIMESTAMP" property="startDate" />
</resultMap>

@Insert({ "insert into Table_B ( Id_A, Id_B, Start_Date )",
    "values ( #{idB},",
    "#{objA,typeHandler=TableATypeHandler}, #{startDate} )" })
@Options(useGeneratedKeys=true, keyProperty="idA")
int insertReturnPK( TableA record );

TableA Type Handler如下所示:

public class TableATypeHandler extends extends BaseTypeHandler<TableA> {
    ...

    @Override
    public void setNonNullParameter( PreparedStatement ps, int colIdx, TableA parameter, JdbcType jdbcType ) throws SQLException {
        // code to set the specified column indexed by colIdx in Table_A
    }
}

最后问题! TableA.insertReturnPK和TableB.insertReturnPK不兼容。或者更具体地说,他们调用TableATypeHandler.setNonNullParameter有两个非常不同的目的:

  1. TableBMapper.insertReturnPK使用colIdx = 2调用它,将第2列设置为Table_B,主键为Table_A,即Table_A.Id_A(整数)
  2. MyBatis 隐式(希望它没有!)在TableBMapper.insertReturnPK调用中使用TableATypeHandler来填充Table_A的列。 换句话说,当它使用colIdx = 2调用TableATypeHandler.setNonNullParameter时,它想要使用tableA.name值(String)设置prepare语句。此外,在此上下文中,为Table_A中的每一列调用setNonNullParameter,而在1.中仅调用一次以获取Table_A的主键。
  3. MyBatis 在2中隐式使用TableATypeHandler可以很容易地避免这个问题。或者将setNonNullParameter改为有2个列索引,即一个与ps(目标列索引)相关的索引和一个peratains to parameter(source column index)。

    有人碰到过这个吗?是否有解决方法?

0 个答案:

没有答案