Mybatis的基本运行流程

Mybatis基本运行流程

总结JDBC的问题:

1、数据库连接创建、释放频繁造成系统资源浪费,从而影响系统性能。如果使用数据库连接池可解决此问题。

2、Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码。

3、使用preparedStatement向占有位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护。

4、对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便。

1.Mybatis介绍

​ MyBatis是一个支持普通SQL查询存储过程高级映射的优秀持久层框架MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装。MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO映射成数据库中的记录

​ mybatis通过xml或注解进行配置,将java对象与sql语句中的参数自动映射生成最终执行的sql语句,并将sql语句执行结果自动映射成java对象,返回给业务层(service)应用。

Mybatis的整体架构

在这里插入图片描述

2.Mybatis的生命周期

​ 正确理解SqlSessionFactory、SqlSessionFactoryBuilder、SqlSession和Mapper的生命周期对于优化Mybatis尤为重要,这样可以使Mybatis高效正确完成;同为重要时Mybatis的生命周期对于理解Myabtis缓存的配置也尤为重要,我这里只做简单的文字介绍(其实也好理解):

(1)SqlSessionFactoryBuilder:作用就是创建一个构建器,一旦创建了SqlSessionFactory,它的任务就算完成了,可以回收。

(2)SqlSessionFactory:作用是创建SqlSession,而SqlSession相当于JDBC的一个Connection对象,每次应用程序需要访问数据库,我们就要通过SqlSessionFactory创建一个SqlSession,所以SqlSessionFactory在整Mybatis整个生命周期中(每个数据库对应一个SqlSessionFactory,是单例产生的)。

(3)SqlSession:生命周期是存在于请求数据库处理事务的过程中,是一个线程不安全的对象(在多线程的情况下,需要特别注意),即存活于一个应用的请求和申请,可以执行多条SQL保证事务的一致性。

(4)Mapper:是一个接口,它的作用是发送SQL(其中的方法相当于JDBC中的Statement),返回我们需要的结果,或者发送SQL修改数据库表,所以它存活于一个SqlSession内,是一个方法级别的东西。当SqlSession销毁的时候,Mapper也会销毁。

为什么SqlSessionFactory是单例的:

​ SqlSessionFactory是创建SqlSession的工厂,但是创建过程中需要反复加载全局配置文件,这一点是十分耗时的,为了优化项目,最好通过单例模式来管理它,使它只能创建一个对象,配置文件加载一次就可以了。(在mybatis整合spring之后,最好的方式是把sqlsessionfactory交给spring来做单例管理)

3.Mybatis的配置

3.1单独使用Mybatis的配置

在这里插入图片描述
1.按照上面的步骤首先定义一个User类

User.java

public class User {
	private Integer id;
	private String username;
	private Integer[] ids;
	private List<Integer> idlist;
	public Integer[] getIds() {
		return ids;
	}
	public void setIds(Integer[] ids) {
		this.ids = ids;
	}
	public List<Integer> getIdlist() {
		return idlist;
	}
	public void setIdlist(List<Integer> idlist) {
		this.idlist = idlist;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", username=" + username + "]";
	}
}

2.接着定义一个Mapper接口:定义了一些方法来操作数据库,方法中具体sql语句的实现在相应的xml文件中。

UserMapper.interface

public interface UserMapper {
	/*
	 * 遵循四个原则:
	 * 		1.方法名和UseMapper.xml中<mapper>标签中sql标签的id属性值相同
	 * 		2.方法的返回值和<mapper>标签中标签的resultType属性值相同
	 * 		3.方法的参数类型和<mapper>标签中标签的parameterType属性值相同
	 * 		4.xml中<mapper>标签的namespace属性值和此接口的全类名相同
	 */
	 User findUserById(Integer id);
}

3.接着定义Mapper的映射文件UserMapper.xml,此文件的作用就是映射方法实现具体的SQL语句。

<mapper namespace="Mapper.UserMapper">
	<!-- 设置一个sql片段 可以SQL语句中在引用-->
	<sql id="selector">
		select * from user
	</sql>
	<select id(方法名)="findUserById" parameterType(方法的参数类型)="Integer" resultType(方法的返回类型)="pojo.User">
		<include refid="selector"/>
        where id = #{id}
	</select>
</mapper>

4.定义了UserMapper和UserMapper.xml之后那么程序如何才能寻找到呢,通过Mybatis的配置文件。

sqlMapConfig.xml

<configuration>
	<!-- 指定加载配置文件 -->
	<properties resource="jdbc.properties"/>
	<!-- 别名设置 -->
	<typeAliases>
		<package name="pojo"/>	
	</typeAliases> 
	<!-- 和Spring整合后这个标签就没用了 -->
	<environments default="development">
		<environment id="development">
			<!-- 使用jdbc事务管理 -->
			<transactionManager type="JDBC" />
			<!-- 数据库连接池 -->
			<dataSource type="POOLED">
				<property name="driver" value="${jdbc.driver}" />
				<property name="url"
					value="jdbc:mysql://localhost:3306/student" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	<!-- 引入User的xml映射文件 我的UserMapper.java
和UserMapper.xml都在Mapper包下-->
	<mappers>
		<package name="Mapper"/>
		<!-- package这种方式需要接口名和xml文件名相同,直接导入包下所有配置文件
		-->
	</mappers>
</configuration>

5.配置好了配置文件创建一个demo实例来加载配置文件并创建sqlSessionFactory

UserDemo.java

public class UserDemo {
	@Test
	//通过id查询值
	public void fun() throws IOException{
//		1.加载配置文件
		InputStream in = Resources.getResourceAsStream("sqlMapConfig.xml");
//		2.创建SqlSessionFactory
		SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
//		3.创建sqlSession
		SqlSession sqlSession=sqlSessionFactory.openSession();
//		4.sqlSeesion动态创建UserMapper实现类
		UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//		5.实现类调用接口的方法,方法和映射文件一一对应
		User user=userMapper.findUserById(1);
		System.out.println(user);
	}

3.2Mybatis整合Spring

​ 单独使用Mybatis时我们需要通过加载配置文件来创建SqlsessionFactory,得到sqlsession,然后通过sqlsession来创建mapper接口的代理类,最后通过代理类来执行sql语句。

​ 整合Spring之后,通过在applicationContext.xml中注入两个类来实现上面所有的操作。原理还是一样,只不过spring替我们简化了操作,并且dateSource的操作放在了spring的配置文件中。

applicationContext.xml

context:property-placeholder location="classpath:jdbc.properties"/>
	<!-- 将连接池注入容器 -->
	<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>
	<!--配置工厂 -->
	<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<!-- 核心配置文件的位置 -->
		<property name="configLocation" value="classpath:sqlMapConfig.xml"/>
	</bean>
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<!-- 扫描包下的所有接口 -->
		<property name="basePackage" value="mapper"/>
		<!-- 这里会自动注入mapper接口
			<bean name="userMapper" class="mapper.UserMapper"/>
		 -->
	</bean>
</beans>

这里的SqlSessionFactoryBean在Spring中最后创建的并不是Bean本身而是sqlSessionFactory

sqlMapConfig.xml文件只需设置一个别名(或者也不设置)

<configuration>
	<!-- 设置别名 -->
	<typeAliases>
		<!-- 2. 指定扫描包,会把包内所有的类都设置别名,别名的名称就是类名,大小写不敏感 -->
		<package name="pojo" />
	</typeAliases>
</configuration>

UserDemo.java

	@Test
	public void testMapper() throws Exception {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserMapper mapper = ac.getBean(UserMapper.class);
		User user = mapper.selectUserById(1);
		System.out.println(user);
	}

这里的getBean会创建UserMapper的实现类

猜你喜欢

转载自blog.csdn.net/qq_38238296/article/details/89292943