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的實現類

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章