You could use a custom type handler to do this. For example:
public class InClauseParams extends ArrayList<String> {
//...
// marker class for easier type handling, and avoid potential conflict with other list handlers
}
Register the following type handler in your MyBatis config (or specify in your annotation):
public class InClauseTypeHandler extends BaseTypeHandler<InClauseParams> {
@Override
public void setNonNullParameter(final PreparedStatement ps, final int i, final InClauseParams parameter, final JdbcType jdbcType) throws SQLException {
// MySQL driver does not support this :/
Array array = ps.getConnection().createArrayOf( "VARCHAR", parameter.toArray() );
ps.setArray( i, array );
}
// other required methods omitted for brevity, just add a NOOP implementation
}
You can then use them like this
@Select("SELECT * FROM foo WHERE id IN (#{list})"
List<Bar> select(@Param("list") InClauseParams params)
However, this will not work for MySQL, because the MySQL connector does not support setArray()
for prepared statements.
A possible workaround for MySQL is to use FIND_IN_SET
instead of IN
:
@Select("SELECT * FROM foo WHERE FIND_IN_SET(id, #{list}) > 0")
List<Bar> select(@Param("list") InClauseParams params)
And your type handler becomes:
@Override
public void setNonNullParameter(final PreparedStatement ps, final int i, final InClauseParams parameter, final JdbcType jdbcType) throws SQLException {
// note: using Guava Joiner!
ps.setString( i, Joiner.on( ',' ).join( parameter ) );
}
Note: I don't know the performance of FIND_IN_SET
, so test this if it is important