发表于: 2020-11-04 14:34:41
1 1427
今天完成的事情:
Mybatis和Spring整合详解:
为什么需要整合
需要spring来管理数据源信息。
需要spring通过单例方式管理SqlSessionFactory,之前单独使用mybatis需要自己编写SqlSessionFactory代码,现在直接在xml文件中直接注入就行了
使用SqlSessionFactory创建SqlSession。(spring和mybatis整合自动完成)
持久层的mapper都需要由spring进行管理,spring和mybatis整合生成mapper代理对象。
编写两种方式:一种使用mapper代理,一种不使用mapper代理
先编写spring-config文件,首先加载db.properties文件,然后再加载数据源,配置连接池参数。之后设置SqlSessionFactory的bean,在其中需要注入两个参数,一个是SqlMapConfig.xml,另外一个是配置的数据源bean。再配置原始DAO接口,在spring中添加studentDAO的bean配置,将定义的SqlSessionFactory对象当作参数注入进去,这样StudentImpl继承SqlSessionDaoSupport类才会起作用。最后编写启用mapper代理模式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"
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
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!-- 加载配置文件-->
<context:property-placeholder location="classpath:db.properties" />
<!-- 数据源,使用DBCP -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxActive" value="10"/>
<property name="maxIdle" value="5"/>
</bean>
<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 加载MyBatis的配置文件 -->
<property name="configLocation" value="SqlMapConfig.xml"/>
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 原始DAO接口 -->
<bean id="studentDao" class="com.jnshu.Dao.StudentDaoImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 指定扫描的包名
如果扫描多个包,每个包中间使用半角逗号分隔 -->
<property name="basePackage" value="com/jnshu/Mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
</beans>
下一步编写mybatis配置文件(SqlMapConfig.xml),设置一下缓存的参数。然后在typeAliases设置实体类的路径,最后在mapper配置中,设置加载mapper映射文件的路径,配置mapper代理借口所在的包名。这个在使用mapper代理后就会注释掉,因为spring有自己的mapper扫描器类,可直接在spring中设置。
缓存起因:有些时候查询数据频率很高,这是很耗费数据库资源的,而且会导致数据库查询效率低。解决方法:将一些变动不大且访问频率较高的数据,防止在一个缓存容器中(很像数据库连接池的概率,也是设置一个容器,存放连接,需要的时候就取出来),查询的时候就直接从这个容器中取出。
mybatis提供一级缓存和二级缓存。
简单了解一些缓存基本概念
配置Studentmapper.xml文件,用于配置SQL映射语句。然后再创建实体类。之后编写DAO层,在同一个文件夹下创建DAO层的实现类
注意查看StudentDaoImpl继承了SqlSessionDaoSupport类,查看SqlSessionDaoSupport类,发现下面有SqlSessionFactory方法和SqlSession方法,这样在StudentDaoImpl类中,就可以直接获取SqlSession对象,进行数据库的增删改查操作。
package com.jnshu.Dao;
import com.jnshu.Pojo.Student;
public interface StudentDao {
public Student findStudentById(int id) throws Exception;
}
package com.jnshu.Dao;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import com.jnshu.Pojo.Student;
public class StudentDaoImpl extends SqlSessionDaoSupport implements StudentDao {
public Student findStudentById(int id){
//继承SqlSessionDaoSupport类,通过this.getSqlSession()得到sqlSession
SqlSession sqlSession = this.getSqlSession();
Student student = sqlSession.selectOne("test.findStudentById",id);
return student;
}
}
编写测试类StudentServiceTest
运行逻辑:和mybatis是差不多的,就是把mybatis配置文件转成了Spring-config.xml配置文件,然后将SqlSessionFactory采用注入的方法注射到StudentDaoImpl类中,之后也是采用SqlSession对象,进行数据库的增删改查操作。
import com.jnshu.Dao.StudentDao;
import com.jnshu.Pojo.Student;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class StudentServiceTest {
private ApplicationContext applicationContext;
//在执行测试方法之前首先获取spring配置文件对象
//注解@before在执行本类所有测试方法之前先调用这个方法
@Before
public void setup() throws Exception{
applicationContext = new ClassPathXmlApplicationContext("classpath:Spring-config.xml");
}
@Test
public void testFindStudentById() throws Exception {
//通过配置资源对象获取StudentDao对象
StudentDao studentDao = (StudentDao) applicationContext.getBean("studentDao");
//调用StudentDao
Student student = studentDao.findStudentById(1);
System.out.println(student.getId() + ":" + student.getName());
}
}
使用mapper代理,不用编写实现类,因为mapper配置文件中的namespace直接和mapper接口绑定了:
mapper配置文件
<?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.jnshu.Mapper.StudentQueryMapper">
<!-- 根据ID查询用户 -->
<select id="findStudentById" parameterType="int" resultType="com.jnshu.Pojo.Student">
SELECT * FROM Student WHERE id=#{id}
</select>
<!-- 新增用户 -->
<insert id="insertStudent" parameterType="com.jnshu.Pojo.Student">
insert into Student(id,name,gender,birthday)
value (#{id},#{name},#{gender},#{birthday})
</insert>
<!-- 删除用户 -->
<delete id="deleteStudent" parameterType="java.lang.Integer">
delete from Student where id=#{id}
</delete>
<!-- 修改用户-->
<update id="updateStudent" parameterType="com.jnshu.Pojo.Student">
update student set name = #{name},gender = #{gender},birthday = #{birthday} where id = #{id}
</update>
</mapper>
mapper接口:
package com.jnshu.Mapper;
import com.jnshu.Pojo.Student;
public interface StudentQueryMapper {
//根据Id查询用户信息
public Student findStudentById(int id) throws Exception;
//添加用户
public void insertStudent(Student student) throws Exception;
//删除用户
public void deleteStudent(int id) throws Exception;
//修改用户
public void updateStudent(Student student) throws Exception;
}
测试类:
运行逻辑和上面的基本没差
import com.jnshu.Mapper.StudentQueryMapper;
import com.jnshu.Pojo.Student;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.text.SimpleDateFormat;
public class StudentMapperTest {
private ApplicationContext applicationContext;
//在执行测试方法之前首先获Spring配置文件对象
//注解Before是在执行本类所有测试方法之前先调用这个方法
@Before
public void setup() throws Exception{
applicationContext = new ClassPathXmlApplicationContext("classpath:Spring-config.xml");
}
//根据id查找用户
@Test
public void testFindStudentById() throws Exception{
//通过配置资源对象获取studentDao对象
StudentQueryMapper studentQueryMapper = (StudentQueryMapper)applicationContext.getBean("studentQueryMapper");
//调用studentDao的方法
Student student=studentQueryMapper.findStudentById(1);
//输出用户信息
System.out.println(student.getId()+":"+student.getName());
}
//添加用户
@Test
public void testInsertStudent() throws Exception{
//通过配置资源对象获取studentDao对象
StudentQueryMapper studentQueryMapper = (StudentQueryMapper)applicationContext.getBean("studentQueryMapper");
//调用studentDao的方法
Student student = new Student();
student.setName("任逍遥");
student.setGender(1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
student.setBirthday(sdf.parse("1995-08-15"));
studentQueryMapper.insertStudent(student);
//输出用户信息
System.out.println(student.getId());
}
//删除用户
@Test
public void deleteStudent() throws Exception{
//通过配置资源对象获取studentDao对象
StudentQueryMapper studentQueryMapper = (StudentQueryMapper)applicationContext.getBean("studentQueryMapper");
//调用studentDao的方法
Student student = new Student();
studentQueryMapper.deleteStudent(3);
//输出用户信息
System.out.println("删除" + student.getId() + "的数据");
}
//更新用户
@Test
public void updateStudent() throws Exception{
//通过配置资源对象获取studentDao对象
StudentQueryMapper studentQueryMapper = (StudentQueryMapper)applicationContext.getBean("studentQueryMapper");
//调用studentDao的方法
Student student = new Student();
student.setId(1);
student.setName("孙悟空");
student.setGender(1);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
student.setBirthday(sdf.parse("2008-01-10"));
studentQueryMapper.updateStudent(student);
//输出用户信息
System.out.println(student);
}
}
明天计划的事情:
完成剩下的步骤
遇到的问题:
配置原始DAO接口,在spring中添加studentDAO的bean配置,将定义的SqlSessionFactory对象当作参数注入进去,这样StudentImpl继承SqlSessionDaoSupport类才会起作用。
不知道为什么这样才会起作用?
将spring-config这个DAO接口注释,运行程序就会报错
org.springframework.beans.factory.No这样的Bean定义异常:没有名为'studentDao'的Bean
第二个问题:为什么接口SqlSessionFactory中有各种SqlSession方法,还需要另外编写接口?
我的解答,为了规范代码,且让我们自己编写一遍,才会知道源代码的意义。
一种编写mybatis的方法,没有另外编写接口.
另外一种编写mybatis的方式,有接口,且使用mapper代理
收获:
基本懂了Mybatis和Spring的运行逻辑
评论