There is no getter for property

前两天工作中遇到这个异常,一开始还以为是实体类漏写set/get方法,经排查不是。

异常大概如下:

1
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'user' in 'class top.nanzx.entity.User'

dao层代码大概如下:

1
2
@Select("SELECT * FROM users WHERE id = #{user.id}")
User getUser(User user)

解决:

1
2
@Select("SELECT * FROM users WHERE id = #{user.id}")
User getUser(@Param("user")User user)

当时有点迷惑平时写demo根本不用加@Param注解,回来测试后得出如下结论(id是参数user的一个属性):

  • 如果SQL语句中使用#{user.id}时,参数必须加@Param注解
  • 如果SQL语句中使用#{id}时,参数可以不加@Param注解

驼峰命名配置开启后没生效

1
2
#开启驼峰命名转换
mybatis.configuration.map-underscore-to-camel-case=true

异常:

1
2
List<User> users = userService.getAllUsers();
system.out.println(users);

可以看到控制台显示mybatis查询成功,有打印出SQL语句和查询结果,但是users这个集合是null。

于是我猜测是没有成功将查询结果封装进对象里,但是我已经配置好了自动转换驼峰命名。

解决:

经过百度,发现可能是因为项目配置了多数据源,mybatis不知道配置哪个数据源,而自定义的sqlSessionFactory默认不会加载mybatis配置。

所以我们需要手动将mybatis配置注册到sqlSessionFactory中:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Bean
@ConfigurationProperties(prefix = "mybatis.configuration")
public org.apache.ibatis.session.Configuration globalConfiguration(){
return new org.apache.ibatis.session.Configuration();
}

@Bean(name = "igmSqlSessionFactory")
public SqlSessionFactory igmSqlSessionFactory(@Qualifier("igmDataSource") DataSource igmDataSource,org.apache.ibatis.session.Configuration configuration) throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(igmDataSource);
sessionFactory.setConfiguration(configuration);
return sessionFactory.getObject();
}

这是官网关于MyBatis-Spring-Boot-Starte的一段翻译:

MyBatis-Spring-Boot-Starter将:

  • 自动检测现有的 DataSource
  • DataSource作为输入使用并通过SqlSessionFactoryBean创建和注册一个SqlSessionFactory实例
  • 将创建并注册一个从SqlSessionFactory中获取的SqlSessionTemplate实例
  • 自动扫描您的映射器,将它们链接到SqlSessionTemplate并将它们注册到Spring上下文中,以便可以将它们注入到您的bean中