MyBatis常见问题

MyBatis FAQ

用MyBatis有点点时间了,也碰到一些问题。放狗搜了之后,发现官方github上的FAQ已经有一些东西,是可以先看看的。

批量插入

之前用MyBatis进行批量插入时,一直都在MyBatis的Mapper.xml里面用foreach拼成一个比较长的SQL,这个时候MySQL和Oracle的拼法还有点不一样。MySQL可以直接用INSERT INTO (id) VALUES (1),(2),(3)这种形式,而Oracle不行,Oracle需要且UNION ALLFROM DUAL或直接BEGIN ... END

后来了解看renren security的源码时候,发现有使用MyBatis Plus,在MyBatis Plus里面的ServiceImpl<M extends BaseMapper<T>, T>类中有个saveBatch方法,看日志发现他不是用接长SQL方法实现的,跟Groovy里面的batch操作是一样的。后来搜索后发现MyBatis其实有个Executor本身就带批量操作功能。。。

1
2
3
4
5
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, true)) {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
userList.forEach(userMapper::insert);
sqlSession.flushStatements();
}

其实我感觉应该是自己对JDBC不熟悉的原因吧,等有时间了去专门学习学习。这个我碰到一个坑,就是Spring boot进行JUnit测试操作的时候,在方法上加上@Transactional,事务回滚。可能是Spring boot test里面本身对事务就是这样处理的?这个有时间也是需要去解决的。// TODO

基本类型(String, Integer等)的列表映射

如果一个查询结果只有一列,这样返回的列表很容易进行映射。但是当一个对象里面有两个属性,一个ID,一个基本类型列表时,在之前查MyBatis文档的时候没有发现,后来在网上搜到了,映射的时候还是用collection,但是里面的只填一个result column。刚好在MyBatis FAQ里面也看到了。搬过来吧。

比如SQL搜索结果是

idstr
1A
2B

Java对象

1
2
3
4
5
@Data
public class SomeBean {
private Integer id;
private List<String> strings;
}

XML映射如下

1
2
3
4
5
6
<resultMap id="" type="SomeBean">
<id column="id" property="id" />
<collection property="strings" ofType="string" javaType="list">
<result column="str" />
</collection>
</resultMap>

另外官方其它的FAQ还有变量使用时#{}${}的区别:$在生成ps的时候,就已经替换了,存在安全问题,#在生成ps的时候,是用?代替,运行的时候再进行值代入。

SQL LIKE,这个有好多实现的方法,比如String自带%,使用bind,直接在SQL里面使用字符拼接。

插入时将自动生成的key返回,在insert映射的时候加入useGeneratedKeys="true" keyProperty="id"

mapper方法传参使用变量名,这个直接使用注解@Param,或直接包装成对象或Map,或mybatis.configuration.use-actual-param-name= true