spring与mybatis整合
首先看一下整体的项目架构:
lib文件夹下为所用到的jar包,因为此处用的c3p0的数据源,引入了相应的 jar包:
包com.cjc.dao和com.cjc.mapper下分别存放MyBatis 的mapper接口文件和 MyBatis 的 XML 映射器文件。
因为为整合说明,为了测试只定义了一个实体类User:
public class User implements Serializable {
private int id;
private String name;
private Date birthday;
private double salary;
//get set 方法和构造方法。。。
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", birthday=" + birthday + ", salary=" + salary + "]";
}
}
创建与之对应的数据表:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`birthday` date DEFAULT NULL,
`salary` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8
UserMapper接口:
public interface UserMapper {
void save(User user);
void update(User user);
User findById(int id);
void delete(int id);
List<User> findAll();
}
对应的XML 映射器文件:userMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cjc.dao.UserMapper">
<select id="findById" parameterType="int" resultType="User">
select * from user where id=#{id}
</select>
<select id="findAll" resultType="User">
select * from user
</select>
<insert id="save" parameterType="User">
insert into user(name,birthday,salary) values(#{name},#{birthday},#{salary})
</insert>
<update id="update" parameterType="User">
update user set name=#{name} birthday=#{birthday} salary=#{salary} where id=#{id}
</update>
<delete id="delete">
delete from user where id=#{id}
</delete>
</mapper>
Notation:
- namespace部分:namespace必须为对应的接口文件的全类名,即:package+className,否则在运行时会报类似如下的错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.cjc.dao.UserMapper.save
- select、update、insert、delete:各sql的id必须与mapper接口中的对应的方法名一致,否则也会报类似如下的错误:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.cjc.dao.UserMapper.save。
至此准备工作已经做完,下面进行spring 与mybatis的配置
在config下面创建spring的配置文件applicationContext.xml:
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
</beans>
第一步配置数据源:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/sm" />
<property name="user" value="root" />
<property name="password" value="root" />
<property name="driverClass" value="com.mysql.jdbc.Driver" />
</bean>
此处数据源使用的C3P0,也可换用其他的数据源,此处数据库连接有关的属性也可在外部properties文件中进行配置,然后在此处进行引用,但是如果用外部属性文件的方式进行配置,会遇到一些坑,本人表示在此处受到了深深的伤害,Mybatis与spring整合过程中遇到的问题会做一个单独的列表,此处不表。。。
在基本的 MyBatis 中,session 工厂可以使用 SqlSessionFactoryBuilder 来创建。而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来替代。接下来 配置SqlSessionFactory:
<bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.cjc.domain" />
<property name="mapperLocations" value="classpath*:com/cjc/mapper/*.xml" />
</bean>
其中:
datasource引用上面定义的数据源
typeAliasesPackage:自动扫描配置别名,在XML 映射器文件中可以直接使用类名
- mapperLocations:该属性使用一个资源位置的 list。 这个属性可以用来指定 MyBatis 的 XML 映射器文件的位置。 它的值可以包含 Ant 样式来加载一个目录中所有文件, 或者从基路径下 递归搜索所有路径
接下来配置接口扫描器:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cjc.dao" />
<property name="sqlSessionFactory" ref="sessionFactory" />
</bean>
配置该项后,Mybatis MapperScannerConfigurer 自动扫描basePackage所定义的包及其子包下的Mapper接口 将Mapper接口生成代理注入到Spring。如果要设置多于一个的包名,可以使用分号或逗号 作为分隔符,将不同的包分开。
注入sqlSessionFactory有如下几种方法:
- 使用sqlSessionFactory注入:使用该属性需要注意关键的一点:不能使用引用外部properties的方法来配置数据源,若使用外部properties的方法配置数据源会出现数据源中定义的url、driver等信息无法读取的情况,因为MapperScannerConigurer实际是在解析加载bean定义阶段的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类,这个时候,PropertyPlaceholderConfigurer还没来得及替换定义中的变量,导致把表达式当作字符串复制
- 使用sqlSessionFactoryBeanName注入,此种注入方式可以使用properties中的定义来配置数据源,因为不会立即初始化sqlSessionFactory, 所以不会引发提前初始化问题。
- 直接删掉property name=”sqlSessionFactory” ref=”sqlSessionFactory”。注意:在没有配置这一行时,必须配置一个以sqlSessionFactory命名的org.mybatis.spring.SqlSessionFactoryBean。
剩下的就是配置事务管理器和声明式事务
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 声明式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
至此,spring与mybatis集成完毕。
源码