公司用的是spring和ibatis,决定学习一下MyBatis,同时再此做一个记录备忘,写这篇总结前学习了好几位同学的博文,再次表示感谢。
一、 基础环境
数据库使用mySql,关于如何创安装MySql,建数据库以及用户,可以参考另外一篇MySql的文章,在此不做介绍。
二、 关于源代码
本文中不会贴完整的源代码,源代码放在oschina,是一个完整的Eclipse Maven工程,感兴趣的同学可以下载并导入。
代码地址:https://git.oschina.net/zengyg/J2EEAPIStudy.git
三、 关键点以及问题
- 需要的配置文件
主要是Spring的配置文件(spring.xml)和MyBatis的配置文件(spring-mybatis.xml)
- MyBatis的xml配置文件
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--
<property name="mapperLocations" value="classpath:com/zengyg/mapping/*.xml"
-->
<property name="mapperLocations" value="classpath*:com/zengyg/**/*Mapper.xml"></property>
</bean>
可以采用映固定文件夹下面的的文件,如:value=”classpath:com/zengyg/mapping/.xml” ,也可以采用更通配的做法:value=”classpath:com/zengyg//Mapper.xml”>,此时在classpath后面的必不可少,缺少型号的话后面的通配符不起作用。 表示可以表示任意多级目录,*表示多个任意字符
- MyBatis的Mapper接口
可以采用单个配置的方式配置Mapper接口,代码如下,指定具体的mapperInterface类和sqlSessionFactory:
<bean id="userInfoDAO" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.zengyg.myibatis.dao.UserInfoDAO" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
这种方式如果系统有很多的配置文件时 全部需要手动编写,更推荐采用Mybatis MapperScannerConfigurer做自动扫描,将Mapper接口生成代理注入到Spring:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zengyg.myibatis.dao" />
</bean>
自动扫描的方式如果是单数据源可以不用指定sqlSessionFactory,因 为 MapperScannerConfigurer 将会创建 MapperFactoryBean之后自动装配,如果是多数据源自动 装配可 能会失效 。这种 情况下 ,你可 以使用 sqlSessionFactoryBeanName 或 sqlSessionTemplateBeanName 属性来设置正确的 bean 名 称
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zengyg.myibatis.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
basePackage 属性是让你为映射器接口文件设置基本的包路径,可以使用分号或逗号作为分隔符设置多于一个的包路径,每个映射器将会在指定的包路径中递归地被搜索到,此处要注意,Spring会把包下面的所有类都做扫描注册,如果包路径下面有非Mapper的类如service就会出一些其他问题,可以进一步采用annotationClass或者markerInterface来过滤。
annotationClass:当指定了annotationClass的时候,MapperScannerConfigurer将只注册使用了annotationClass注解标记的接口。
markerInterface:markerInterface是用于指定一个接口的,当指定了markerInterface之后,MapperScannerConfigurer将只注册继承自markerInterface的接口。
如果上述两个属性都指定了的话,那么MapperScannerConfigurer将取它们的并集,而不是交集。即使用了annotationClass进行标记或者继承自markerInterface的接口都将被注册为一个MapperFactoryBean,比较简单的做法是顶一个顶层的接口,用basePackage加markerInterface组合。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zengyg" />
<property name="markerInterface" value="com.zengyg.myibatis.dao.baseDAO"/>
<!--
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
-->
</bean>
- 遇到的一些问题
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
一般的原因是Mapper interface和xml文件的定义对应不上,需要检查包名,namespace,函数名称等能否对应上,需要比较细致的对比,我经常就是写错了一两个字母搞的很长时间找不到错误
1:检查xml文件所在的package名称是否和interface对应的package名称一一对应
2:检查xml文件的namespace是否和xml文件的package名称一一对应
3:检查函数名称能否对应上
4:去掉xml文件中的中文注释
5:随意在xml文件中加一个空格或者空行然后保存
另外在用maven打包时,maven默认不会打包类路径下的xml文件,所以mapper.xml文件也不会打包到classpass下,也会报这个错误,在build下面作如下修改:
<build>
<finalName>J2EEAPIStudy</finalName>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>