结构示意图:
【1】Model
User 代码如下:
import java.io.Serializable; import java.util.Date; /*implements Serializable*/ public class User implements Serializable{ private int id; private String name; private Date birthday; private double salary; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public User(int id, String name, Date birthday, double salary) { super(); this.id = id; this.name = name; this.birthday = birthday; this.salary = salary; } public User() { super(); } @Override public String toString() { return "User [birthday=" + birthday + ", id=" + id + ", name=" + name + ", salary=" + salary + "]"; } }
【2】UserMapper.class
接口类,方法与userMapper.xml中id一一对应 !!
其实就是DAO,用来进行数据库操作,接口实例如下:
import java.util.List; import com.web.model.User; public interface UserMapper { public void addUser(User user); public void updateUser(User user); public void deleteUser(int id); public User getUserById(int id); public List<User> getUsers(); }
可以看到,接口上没有使用注解,那么就肯定存在一个*mapper.xml与之对应。
【3】userMapper.xml
前面未集成Spring时,映射文件名字可以与model不同。此处,映射文件名字需与接口类,namespace保持一致。
其中,xml的<mapper namespace="com.web.mapper.UserMapper">
,一定要大写!!
- 定义了接口中的方法对应的 sql 与返回类型;
- namespace 为 接口的完全限定类名;
<mapper namespace="com.web.mapper.UserMapper"> <!-- the namespace is different from Mybatis -1 ,here must be UserMapper ,not userMapper !!! --> <!-- Open two level cache --> <cache></cache> <!-- 可以解决model属性名与数据表中column列名不一致问题 jdbcType一定要大写 --> <resultMap type="User" id="UserMap"> <!-- type = "User" || type="user 都可以"--> <id property="id" column="user_id" javaType="int" jdbcType="INTEGER"/> <result property="name" column="user_name" javaType="string" jdbcType="VARCHAR"/> <result property="birthday" column="user_birthday" javaType="date" jdbcType="TIMESTAMP"/> </resultMap> <select id="getUserById" parameterType="int" resultMap="UserMap"> select * from s_user where user_id=#{id} </select> <delete id="deleteUser" parameterType="int" > delete from s_user where user_id=#{id} </delete> <!--如果applicationContext.xml中不配置 <property name="typeAliasesPackage" value="com.web.model"></property> 将必须使用全类名 !!! --> <update id="updateUser" parameterType="com.web.model.User" > update s_user set user_name=#{name},user_birthday=#{birthday} ,user_salary = #{salary} where user_id=#{id} </update> <insert id="addUser" parameterType="com.web.model.User" > insert into s_user(user_name,user_birthday,user_salary) values(#{name},#{birthday},#{salary}) </insert> <!-- model's attr(name) different from column(user_name), so the result use UserMap --> <select id="getUsers" resultMap="UserMap"> select * from s_user </select> </mapper>
项目中使用该xml有几种方式:
放到与UserMapper同一个路径下,通常在同一个包下;
使用import手动引入到applicationContext.xml中;
使用MapperScannerConfigurer在sqlSessionFactory中配置mapperLocations
【4】applicationContext.xml
Spring集成mybatis配置文件,不再需要单独的Mybatis.xml文件。数据源,环境,接口映射等通常都在Spring配置文件中。
实例如下:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:jdbc.properties</value> </list> </property> </bean> <!--使用注解情况下,配置该属性标签,将会自动扫描加载使用了类似注解@Controller、@Service等的bean--> <!-- <context:component-scan base-package="com"></context:component-scan>--> <!-- 数据源配置, 使用 DriverManagerDataSource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" > <property name="driverClassName" value="${driver}" /> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> </bean> <!-- mybatis的SQLSession的工厂 :SqlSessionFactoryBean--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 不使用注解的情况下,配置该属性,就可以使用简单类名 !! instead of com.web.model.User --> <property name="typeAliasesPackage" value="com.web.model"></property> <!--自动扫描加载到对应的mapper xml--> <!--<property name="mapperLocations" > <list> <value>classpath*:com/web/mapper/**/*.xml</value> </list> </property>--> </bean> <!-- mybatis自动扫描加载sql映射文件/接口:MapperScannerConfigurer --> <!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">--> <!-- <property name="basePackage" value="com.web.mapper" />--> <!-- 可以考虑使用通配符 * 扫描多个包 --> <!-- <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>--> <!-- </bean>--> <!-- 若不使用自动扫描映射文件,则需要手动导入 如下 --> <!-- if here load this ,you can use resource in your test java code; at the same time ,you can drop org.mybatis.spring.mapper.MapperScannerConfigurer --> <import resource="config/web/spring/spring-userMapper.xml"/> <!-- 事务管理 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 使用声明式事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
将接口与sql文件联系起来有三种方法:
① 使用MapperScannerConfigurer;
② 在接口类上使用注解,点击查看注解类;
③ 使用import引入定义mapperInterface
接口的xml
<import resource="config/web/spring/spring-userMapper.xml"/>
【5】spring-userMapper.xml
如果不配置org.mybatis.spring.mapper.MapperScannerConfigurer则必须使用该(spring-userMapper.xml)文件或者使用类注解的形式。否则需要手动导入到applicationContext.xml(MapperScannerConfiguer适合集成开发–将所有的mapp.xml放在一起,也可以考虑使用通配符。)
MapperScannerConfiguer详解
MapperScannerConfigurer 支持过滤由指定的创建接口或注解创建映射器 。 annotationClass 属性指定了要寻找的注解名称。 markerInterface 属性指定了要寻找的父接口。 如果两者都被指定了,加入到接口中的映射器会匹配两种标准。 默认情况下,这两个属性都是 null,所以在基包中给定的所有接口可以作为映射器加载。 (可以看到,本文中的作为映射器使用的dao 接口并没有添加 @Repository注解) 被发现的映射器将会使用 Spring 对自动侦测组件(参考 Spring 手册的 3.14.4)默认的命名策略来命名。 也就是说,如果没有发现注解,它就会使用映射器的非大写的非完全限定类名。 但是如果发现了@Component 或 JSR-330 的@Named 注解,它会获取名称。 注意你可以配置到org.springframework.stereotype.Component , javax.inject.Named(如果你使用 JSE 6 的话) 或你自己的注解(肯定是自我注解)中,这样注解将会用作生成器和名称提供器。
注意:
如果Mapper类使用类似于,UserMapper.java 和UserMapper.xml(userMapper.xml)。
则使用注解依赖时
@Resource(name="userMapper") private UserMapper userMapper; @Resource(name="UserMapper")---错误,通过反射构建bean,默认第一个字母小写。
如果Mapper类使用类似于,IUserMapper.java 和IUserMapper.xml。
使用注解依赖时:
@Resource(name="IUserMapper") private IUserMapper userMapper; @Resource(name="iUserMapper")将出错,会查找不到该bean !
故,建议使用如下方式:(spring-userMapper.xml)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> <property name="mapperInterface" value="com.web.mapper.UserMapper" /> </bean> </beans>
6.测试代码
SpringJUnit4ClassRunner环境下测试:
import java.util.Date; import java.util.List; import javax.annotation.Resource; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.web.mapper.UserMapper; import com.web.model.User; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("/applicationContext.xml") public class TestSM { @Resource(name="userMapper") private UserMapper userMapper; @Test public void addUser(){ User user = new User(-1, "mili3", new Date(), 5000.6); userMapper.addUser(user ); } @Test public void updateUser(){ User user = new User(1, "mili2", new Date(), 5000.6); userMapper.updateUser(user ); } @Test public void deleteUser(){ userMapper.deleteUser(2); } @Test public void getUserById(){ User user = userMapper.getUserById(3); System.out.println(new Date()); System.out.println(user); } @Test public void getUsers(){ List<User> users = userMapper.getUsers(); System.out.println(users); } }