-
spring 为何要和mybatis整合?
- mybatis 框架用于持久化对象。
- spring 框架包含一系列框架,其中spring bean是一个对象容器。可以通过该框架实现对象的创建,实现松耦合。
- spring 与mybatis整合的目的,就是利用spring bean创建持久化对象,当然该对象采用了mybatis框架,来实现持久化功能。
-
mybatis如何实现持久化?
1)SqlSessionFactor对象创建SqlSession对象。
SqlSession sess = sfc.openSession();
2)SqlSession获得Mapper代理对象。
GoodsMapper gm = sess.getMapper(GoodsMapper.class);
先定义对象持久化的接口(GoodsMapper),mybatis会根据配置信息生成实现了该接口的代理对象。
2.1)框架是如何获取配置信息的呢?
在第一步获取SqlSessionSq对象时,需要一个SessionFactor的工厂对象,该对象创建方法
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactoryBuilder sb = new SqlSessionFactoryBuilder();
SqlSessionFactory sfc = sb.build(reader);
mybatis-config.xml配置文件中包含了相关信息。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306
/book?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="common" />
<property name="password" value="x3507@jxnu" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/GoodsMapper.xml"/>
<mapper resource="mapper/TypesMapper.xml"/>
</mappers>
</configuration>
配置文件指定了数据库连接配置,以及接口代理类如何实现的配置信息(<mappper>标签)。
2.2)接口方法是如何映射(Mapper)?
看看GoodsMapper.xml文件是如何定义的。
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.edu.jxnu.sse.mapper.GoodsMapper">
<resultMap id="BaseResultMap" type="cn.edu.jxnu.sse.domain.Goods">
<id column="good_id" jdbcType="INTEGER" property="goodId" />
<result column="good_name" jdbcType="VARCHAR" property="goodName" />
<association javaType="cn.edu.jxnu.sse.domain.Types" property="type" >
<id column="type_id" property="typeId"/>
<result column="type_name" property="typeName"/>
</association>
</resultMap>
<select id="findAll" resultMap="BaseResultMap" >
select g.good_id good_id,g.good_name good_name,t.type_id type_id,t.type_name type_name from
goods g,types t where t.type_id=g.type_id
</select>
</mapper>
简单的说,上述配置文件定义了代理类如何实现GoodsMapper接口中findAll方法。持久化操作,无非是通过sql语句访问数据库,因此,该配置文件主要通过定义sql语句来实现接口中的相关方法。
3)通过该Mapper代理对象实现持久化操作。
List<Goods> rs = gm.findAll();
-
spring bean 框架的作用:创建对象(对象容器)。
Java中,需要一个类的对象,通常可利用硬编码(java对象创建语句)方式来获得。
class UserService{
UserDao userDao=new UserDaoJdbcImpl();
......
}
硬编码的问题是耦合度高。上述代码中,UserService依赖于UserDaoJdbcImpl类。如果要修改UserService的持久化方法,则需要修改源代码
class UserService{
UserDao userDao=new UserDaoMybatisImpl();
......
}
spring bean框架利用反射机制来生成对象,避免了硬编码的问题。
-
spring bean如何创建对象?
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-mybatis.xml");
SqlSessionFactory ssf=(SqlSessionFactory) ctx.getBean("sqlSessionFactory");
创建bean容器:ApplicationContext,再由容器返回相应的Bean对象。sqlSessionFactory是什么样的一个对象,则需要通过以下配置文件来描述。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-4.0.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/book?useUnicode=true&characterEncoding=utf8" />
<property name="user" value="common" />
<property name="password" value="x3507@jxnu" />
<property name="maxPoolSize" value="30" />
<property name="minPoolSize" value="10"/>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.edu.jxnu.sse.mapper" />
</bean>
</beans>
从配置文件中可知,容器返回一个org.mybatis.spring.SqlSessionFactoryBean的一个对象。
-
spring 与mybatis怎么整合?
开头说到,spring 与mybatis整合的目的,就是利用spring bean创建持久化对象。原理很简单:在该配置文件配置一个持久化的对象,通过bean容器返回即可。回头看看mybatis如何生成持久化的对象的,把下列的硬编码改成配置文件就行了。
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactoryBuilder sb = new SqlSessionFactoryBuilder();
SqlSessionFactory sfc = sb.build(reader);
SqlSession sess = sfc.openSession();
GoodsMapper gm = sess.getMapper(GoodsMapper.class);
该段代码重点是生成一个实现了接口GoodsMapper的代理类,该类实现了持久化工作。
mybatis提供的MapperFactoryBean类可以返回一个这样的代理类对象。因此,可配置如下Bean。
<bean id="userMapper"
class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface"
value="cn.edu.jxnu.sse.mapper.GoodsMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
其中<property name="mapperInterface" value="cn.edu.jxnu.sse.mapper.GoodsMapper" />表示代理类要实现的接口。
<property name="sqlSessionFactory" ref="sqlSessionFactory" /> 表示生成代理类需要的会话工厂。需要在配置文件中配置该对象。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>
以上配置定义了一个SqlSessionFactoryBean的对象,该对象主要是给MapperFactoryBean对象提供引用。
<property name="mapperLocations" value="classpath:mapper/*.xml" /> 定义了相关配置文件位置。给配置文件作用前文已经描述过了。
<property name="dataSource" ref="dataSource" />定义了持久操作的数据源。该数据源对象需要另一个Bean来定义。
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/book?
useUnicode=true&characterEncoding=utf8" />
<property name="user" value="common" />
<property name="password" value="x3507@jxnu" />
<property name="maxPoolSize" value="30" />
<property name="minPoolSize" value="10"/>
</bean>
至此,我们把配置文件完整描述如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-4.0.xsd">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/book?
useUnicode=true& characterEncoding=utf8" />
<property name="user" value="common" />
<property name="password" value="x3507@jxnu" />
<property name="maxPoolSize" value="30" />
<property name="minPoolSize" value="10"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:mapper/*.xml" />
</bean>
<bean id="userMapper"
class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface"
value="cn.edu.jxnu.sse.mapper.GoodsMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>
如在服务层需要持久化对象
class UserService{
public void save(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-mybatis2.xml");
UserDao userDao =(SqlSessionFactory) ctx.getBean("userDao");
User u=new User("张三",35);
userDao.savel(u);
}
}
上述代码中,持久化对象userDao是从容器生成的,如果更换相应的实现类,不需要修改源代码,修改Bean的配置文件就可以了。
当然,实际代码中,持久化对象可以直接注入。
<bean id="userMapper"
class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface"
value="cn.edu.jxnu.sse.mapper.GoodsMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="userService" class="cn.edu.jxnu.sse.service.UserService"/>
<property name="userDao" ref="userMapper"/>
</bean>
在代码中直接通过spring容器返回UserService对象,该对象已经关联了相关的持久化对象。
在web应用中,spring-mvc框架会根据配置从容器中返回相关对象,无需编写代码从容器中返回。相关内容涉及到spring mvc框架知识。