目录
注册会话工厂(SqlSessionFactory),不用手动创建
自动创建线程安全的会话,自动获取mapper接口的代理类并放入spring容器
一.Mybatis整合Spring的好处
Mybatis整合Spring给我们带来的好处
- Spring可以帮我们管理对象
- 简化方法的调用
Mybatis利用Spring的扩展点,把自己与Spring进行了整合
注册会话工厂(SqlSessionFactory),不用手动创建
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置主配置文件地址--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <!-- 注册mapper.xml--> <property name="dataSource" ref="dataSource"/> </bean>
原理:
org.mybatis.spring.SqlSessionFactoryBean这个类实现了FactoryBean、InitializingBean、ApplicationListener
熟悉Spring流程的应该知道FactoryBean是Spring注册bean的一种特殊的方式,他的getObject方法可以自定义的创建对象,他会解析我们的Mybitis的配置文件,最终把SqlSessionFactoryBean注册到Spring的容器,然后我们getbean(SqlSessionFactoryBean)的时候就可以得到SqlSessionFactory对象
自动创建线程安全的会话,自动获取mapper接口的代理类并放入spring容器
DefaultSqlSession是线程不安全的,所以我们并不可以直接用DefaultSqlSession。
SqlSessionTemplete 是他的替代品,他采用jdk动态代理 每次创建一个新的DefSqlSession
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!--指定包名, 包名是mapper接口所在的包名。 MapperscannerConfigurer会扫描这个包中的所有接口,把每个接口都执行 一次getMapper()方法 ,得到每个接口的代理对象。 创建好的代理对象放入到spring的容器中的。--> <property name="basePackage" value="com.ws.mapper"/> </bean>
原理:
org.mybatis.spring.mapper.MapperScannerConfigurer这个类实现了BeanDefinitionRegistryPostProcessor接口,他也是注册bean的一种方式,实现他的方法可以直接
注册beanDifinition.他会扫描我们注册的mapper接口,把扫描到的接口name注册成beanDefinition的beanName,setBeanClass时,他传入了 MapperFactoryBean对象,MapperFactoryBean是又实现了FactoryBean的类,他的getObject方法就是获取SqlSession,调用getMapper方法,所以Mybatis会帮他动态代理生成mapper接口的代理对象。
所以就不用我们手动的创建SqlSession,也不用手动调用getMapper.
他会先获取SqlSessionTemplete
二.依赖、配置与实现
1.加入相关依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- Mybitis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!-- mybitis整合spring-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<!-- 做事务依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!-- jdbc依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<!--druid数据源依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<!--lombok依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
<!--Mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
</dependencies>
2.编写配置文件
spring主配置文件
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--声明jdbc属性文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--声明数据源Datasource,作用是连接数据库 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="20"/>
</bean>
<!--声明的是mybatis中提供的SqlSessionFactoryBean类 ,这个类内部创建SqlSessionFactory的 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 配置主配置文件地址-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!-- 注册mapper.xml-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象。-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--指定包名, 包名是mapper接口所在的包名。
MapperscannerConfigurer会扫描这个包中的所有接口,把每个接口都执行
一次getMapper()方法 ,得到每个接口的代理对象。
创建好的代理对象放入到spring的容器中的。-->
<property name="basePackage" value="com.ws.mapper"/>
</bean>
<context:component-scan base-package="com.ws.service"/>
</beans>
Mybatis配置文件
<?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>
<settings>
<!-- 打印查询语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<setting name="localCacheScope" value="SESSION"/>
<!-- 控制全局缓存(二级缓存),默认 true-->
<setting name="cacheEnabled" value="true"/>
<!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
<!--<setting name="proxyFactory" value="CGLIB" />-->
</settings>
<typeAliases>
<typeAlias alias="student" type="com.ws.vo.Student" />
</typeAliases>
<!--配置插件-->
<!-- <plugins>-->
<!-- <plugin interceptor="com.github.pagehelper.PageInterceptor">-->
<!-- </plugin>-->
<!-- </plugins>-->
<mappers>
<!--一个mapper标签指定 一个文件的位置。
从类路径开始的路径信息。target/clasess(类路径 )
-->
<mapper resource="mapper/StudentMapper.xml"/>
</mappers>
</configuration>
3.代码流程
实体类
@Data
public class Student implements Serializable {
private Integer id;
private String name;
private Integer age;
private Integer clazzNo;
public Student(Integer id, String name, Integer age, Integer clazzNo) {
this.id = id;
this.name = name;
this.age = age;
this.clazzNo = clazzNo;
}
}
mapper接口
public interface StudentMapper {
/**
* 查询所有学生信息
* @return
*/
// List<Student> queryAllStudents(RowBounds rowBounds);
List<Student> queryAllStudents();
/**
* 根据ID查学生信息
* @return
*/
Student querySyudentById(Integer id);
/**
* 添加学生
* @return
*/
int addStudent(Student student);
/**
* 修改学生信息
* @return
*/
int updateStudentById(Student student);
/**
* 删除学生
* @return
*/
int deletStudentById(Integer id);
// /**
// * 查询学生和班级
// * @return
// */
// StudentAndClazz queryStudentAndeClazzById(Integer id);
}
mapper.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.ws.mapper.StudentMapper">
<cache type="org.apache.ibatis.cache.impl.PerpetualCache"
size="1024"
eviction="LRU"
flushInterval="120000"
readOnly="false"/>
<select id="queryAllStudents" resultType="com.ws.vo.Student">
select id, name, age, clazz_no from student
</select>
<select id="querySyudentById" parameterType="int" resultType="student">
select id, name, age, clazz_no from student where id=#{id}
</select>
<insert id="addStudent">
insert into student (id,name,age,clazz_no)values (#{id},#{name},#{age},#{clazzNo})
</insert>
<update id="updateStudentById" parameterType="student">
update student set name=#{name}, age=#{age}, clazz_no=#{clazzNo} where id=#{id}
</update>
<delete id="deletStudentById" parameterType="int">
delete from student where id = #{id}
</delete>
<!-- 根据clazz_no查询clazz信息,一对一查询的结果,嵌套查询 -->
<!-- <resultMap id="studentAndClazz" type="com.ws.vo.StudentAndClazz">-->
<!-- <id column="id" property="id" jdbcType="INTEGER"/>-->
<!-- <result column="name" property="name" jdbcType="VARCHAR"/>-->
<!-- <result column="age" property="age" jdbcType="INTEGER"/>-->
<!-- <result column="clazz_no" property="clazzNo" jdbcType="INTEGER"/>-->
<!-- <result column="clazz_name" property="clazzName"/>-->
<!-- </resultMap>-->
<!-- <select id="queryStudentAndeClazzById" parameterType="int" resultMap="studentAndClazz">-->
<!-- select s.id, s.name, s.age, s.clazz_no, c.clazz_name from student s join clazz c on s.clazz_no=c.id where s.id = #{id}-->
<!-- </select>-->
<!-- <select id="queryStudentAndeClazzById" parameterType="int" resultType="com.ws.vo.StudentAndClazz">-->
<!-- select s.id, s.name, s.age, s.clazz_no clazzNo, c.clazz_name clazzName from student s join clazz c on s.clazz_no=c.id where s.id = #{id}-->
<!-- </select>-->
</mapper>
Service
@Service
public class StudentService {
@Autowired
public StudentMapper studentMapper;
public List<Student> queryAllStudents() {
return studentMapper.queryAllStudents();
}
}
Test
public class App
{
public static void main( String[] args )
{
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentService studentService = applicationContext.getBean(StudentService.class);
List<Student> studentList = studentService.queryAllStudents();
System.out.println(Arrays.toString(studentList.toArray())
.replaceAll("\\[|\\]","")
.replaceAll("\\)\\,","\\)\n"));
// System.out.println(applicationContext.getBeanDefinitionNames());
}
}
总结:
Mybatis整合Spring实际上就是利用了Spring的扩展,所以我们要清楚Spring留给我们的钩子方法。一定要知道Spring注册bean的那几种方式。点击学习注册bean的方式