目录
前言
在学完Spring之后,回顾之前学习的MyBatis,然后就想到Spring可以整合MyBatis进行开发。而在使用MyBatis的时候,可以发现conf.xml的文件中最为主要的配置有两个,一个是数据库连接信息的配置,还有一个是Mapper.xml文件的导入配置,之后就是其它全局配置和别名设置等等了;
而通过Reader类创建对象read读取到conf.xml的配置信息,之后再通过利用read创建SqlsessionFactory类对象获取相关的信息(最主要的还是数据库信息和mapper映射信息):
//引入配置
Reader reader = Resources.getResourceAsReader(“org/entity/config/conf.xml”);
//建立会话工厂SqlSessionFactory
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
而会话sqlsession是通过SqlsessionFactory通过调用openSession方法建立起来的,然后会话通过getMapper(Mapper.class)方法创建代理,之后就可以操作数据了。
总的来说就是SqlsessionFactory类对象要最基本要获得数据库连接信息和Mapper.xml导入;
而实际上,通过Spring和MyBatis的整合不仅可以在IOC容器中实现创建SqlsessionFactory类对象的工作,还可以让将MyBatis中conf.xml的配置信息逐渐转移到IOC容器中来,最后实现干掉conf.xml。
使用到的包
此次测试用的是maven工程,所以按照以下jar进行依赖导入:
mybatis-spring.jar spring-tx.jar spring-jdbc.jar spring-expression.jar
spring-context-support.jar spring-core.jar spring-context.jar
spring-beans.jar spring-aop.jar spring-web.jar commons-logging.jar
commons-dbcp.jar ojdbc.jar mybatis.jar log4j.jar commons-pool.jar
使用Dao类继承SqlSessionDaoSupport实现基本的整合:
- 起初要创建好student数据表和Student类:
package org.my.entity;
public class Student {
int stuNo;
String stuName;
int stuAge;
public Student(){}
public Student(int stuNo, String stuName, int stuAge) {
this.stuNo = stuNo;
this.stuName = stuName;
this.stuAge = stuAge;
}
public int getStuNo() {
return stuNo;
}
public void setStuNo(int stuNo) {
this.stuNo = stuNo;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public int getStuAge() {
return stuAge;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
}
- 然后建立StudentMapper.xml与StudentMapper.java并用namespace进行对接
//StudentMapperMapper.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">
<!-- namespace:该mapper.xml映射文件的唯一标识符 -->
<mapper namespace="org.my.Mapper.StudentMapper">
<cache/>
<select id="queryStudentById" resultType="org.my.entity.Student" parameterType="int" >
select * from student where stuno = #{stuNo}
</select>
<!--增加学生-->
<insert id="addStudent" parameterType="org.my.entity.Student" >
insert into student(stuno,stuname,stuage) values(#{stuNo},#{stuName},#{stuAge})
</insert>
</mapper>
//StudentMapper.java
package org.my.Mapper;
import org.my.entity.Student;
public interface StudentMapper {
public void addStudent(Student student);
}
- 建立Dao实现类
package org.my.dao;
import org.apache.ibatis.session.SqlSession;
import org.my.Mapper.StudentMapper;
import org.my.entity.Student;
import org.mybatis.spring.support.SqlSessionDaoSupport;
public class StudentDaoImpl extends SqlSessionDaoSupport implements StudentMapper {
//继承SqlSessionDaoSupport主要是为了拿到getSqlSession()的方法进行创建
public void addStudent(Student student) {
SqlSession sqlseesion = super.getSqlSession();
StudentMapper studentDao = sqlseesion.getMapper(StudentMapper.class);
studentDao.addStudent(student );
}
}
- 建立IStudentService接口及实现类StudentServiceImpl
//接口IStudentService.java
public interface IStudentService {
public void addStudent(Student student);
}
//StudentServiceImpl.java
package org.my.Service;
import org.my.Mapper.StudentMapper;
import org.my.entity.Student;
public class StudentServiceImpl implements IStudentService {
private StudentMapper studentMapper;
public StudentMapper getStudentMapper() {
return studentMapper;
}
public void setStudentMapper(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
//通过接口上调,实现增加学生的功能
public void addStudent(Student student) {
studentMapper.addStudent(student);
}
}
- 在IOC容器中配置
(由于是使用maven,所以所有的xml文件我都是存放在resources中直接调用,如在其他地方请使用classpath:+相对路径)
<?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.xsd">
<bean id="student" class="org.my.entity.Student">
<property name="stuNo" value="112"></property>
<property name="stuAge" value="10"></property>
<property name="stuName" value="em"></property>
</bean>
<!--第一种依赖于Dao类的方法-->
<bean id="studentmapper0" class="org.my.dao.StudentDaoImpl">
<property name="sqlSessionFactory" ref="mysqlSessionFactory"></property>
</bean>
<bean id="studentsevice" class="org.my.Service.StudentServiceImpl">
<property name="studentMapper" ref="studentMapper0"></property>
</bean>
<!--加载db.properties文件-->
<bean id="db.properties" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
<property name="locations" value="db.properties"></property>
</bean>
<!--配置数据库信息替换Mybatis的conf.xml文件-->
<bean id="mydataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
<property name="maxActive" value="${maxActive}"></property>
<property name="maxIdle" value="${maxIdle}"></property>
</bean>
<!--在SpringIOC容器中 创建MyBatis的核心类sqlSessionFactory-->
<!--SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);-->
<bean id="mysqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--数据库信息-->
<property name="dataSource" ref="mydataSource"></property>
<!--Mapper映射文件-->
<property name="mapperLocations" value="StudentMapper.xml"></property>
<!--加载Mybatis配置文件-->
<!--<property name="configLocation" value="conf.xml"></property>-->
</bean>
</beans>
db.properties
注:
-
db.properties存放了数据库的连接信息,引入之后的使用方法与之前MyBatis的配置引入使用方法同理;
-
数据库的配置用到的是dbcp.jar中的BasicDataSource进行配置,与JDBC提交方式不同,JDBC需要手动commit()提交,而dbcp实现自动提交功能。
-
SqlSessionFactory 的建立是通过SqlSessionFactoryBean类的,主要配置信息有数据库信息引入,Mapper.xml文件的导入,而加载Mybatis配置文件可用可不用,主要是为了一些不熟悉在IOC容器中设置MyBatis配置而直接通过导入MyBatis的配置文件获得相应功能。这里我注掉没有用,因为我的目标之一就是干掉conf.xml配置文件。
-
sqlSessionFactory的赋值主要是SqlSessionDaoSupport 或其父类的属性的需要,毕竟通过sqlSessionFactory建立,才能使用到getSession()方法进行操作。
-
如果出现以下报错,请在论坛中查找相关解决方法,并不是特别复杂,在此就不细讲了
WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows R
测试:
public class test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
IStudentService studentsevice = (StudentServiceImpl)context.getBean("studentsevice");
Student student = (Student) context.getBean("student");
studentsevice.addStudent(student);
}
}
测试成功:
整合的IOC中的主要赋值
1.用dbcp.jar中的BasicDataSource建立数据库连接信息。
2. 用mybatis-spring.jar中的SqlSessionFactoryBean建立SqlSessionFactory会话工厂的< bean>,之后 导入配置好地数据库信息 和 导入Mapper.xml。
3. 根据Dao实现类继承SqlSessionDaoSupport 需要赋值导入SqlSessionFactory从而得到SqlSession会话,并通过getSqlSession()的方法获得Sqlsession,之后的操作在实现类Dao中实现。
4. 通过IStudentService接口上调,以及StudentService在< bean>的创建赋值关联实现类,从而实现最终数据库的操作。
第二种方法:MapperFactoryBean简化掉Dao层
上面是通过Dao实现类继承SqlSessionDaoSupport 类进行操作,而MyBatis-spring.jar中提供了一个类MapperFactoryBean,通过创建< bean>而可以承担Dao实现类的工作,以下是第二种方式MapperFactoryBean的具体实现:
<!--第二种干掉Dao类的方法-->
<bean id="studentMapper1" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="sqlSessionFactory" ref="mysqlSessionFactory"></property>
<property name="mapperInterface" value="org.my.Mapper.StudentMapper"></property>
</bean>
<bean id="studentsevice" class="org.my.Service.StudentServiceImpl">
<property name="studentMapper" ref="studentMapper1"></property>
</bean>
这个时候就不需要Dao实现类了。
第三种方法: MapperScannerConfigurer扫描包
- 通过MyBatis-spring.jar提供的MapperScannerConfigurer类可以实现扫描特定包下面的多个Mapper.xml,如果是多个包,用逗号隔开。
<!--第三种方式,可同时导入多个Mapper-->
<!--不需要写id属性-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="mysqlSessionFactory"></property>
<property name="basePackage" value="org.my.Mapper"></property>
</bean>
<!--ref的赋值是Mapper接口类名并且第一个字母小写-->
<bean id="studentsevice" class="org.my.Service.StudentServiceImpl">
<property name="studentMapper" ref="studentMapper"></property>
</bean>
注意以下几点:
-
MapperScannerConfigurer其实有sqlSessionFactory的,但使用sqlSessionFactoryBeanName和value赋值是由于两种数据库信息调用的情况不同,前者经常出现数据库配置出现调用错误的问题,而后者不会,详细解释请在论坛上查找它们的区别,有大牛会详细解释原因。
-
扫描包设置不需要设置ID值,也不建议设置;而studentsevice的调用中,ref的赋值是Mapper接口类名并且第一个字母小写。个人认为是扫描包< bean>的作用,个人认为是在扫描的时候,扫描器就自动生成studentMapper以供使用了,而使用IDEA可以根据提示进行补全。
此文章是个人的Spring学习笔记,用于之后的温习回顾。。。。。。