在前面的MyBatis部份內容中,咱們已經能夠獨立的基於MyBatis構建一個數據庫訪問層應用,可是在實際的項目開發中,咱們的程序不會這麼簡單,層次也更加複雜,除了這裏說到的持久層,還有業務邏輯層、視圖層等等,隨着代碼量和需求複雜度逐漸增加,對象的建立、管理以及層與層之間的耦合度等等問題隨之而來。Spring是目前比較流行的框架,它解決了諸多例如層次之間鬆耦合、幫助管理對象等問題。若是是有準備學習MyBatis的人,應該或多或少都學習過或者瞭解過Spring了,本篇要經過Spring集成MyBatis,首先要對Spring核心的概念IOC和AOP有個基本認識。html
首先回顧下IOC,控制反轉(Inversion of Control,英文縮寫爲IOC),前面講到的層與層之間的耦合問題在Spring中,即經過控制反轉解決的,那麼控制具體是控制什麼,反轉是怎樣反轉?咱們在學習初期,建立對象用到最多的每每就是new語句,若是須要一個Person類的實例對象,咱們就能夠經過 Person p = new Person(); 獲取咱們想要的,進一步引伸,在咱們的開發中,若是業務邏輯Service層須要一個持久層Dao的實例,那麼咱們也能夠在這個Service中直接new一個Dao實例,這樣就至關因而咱們本身在控制這個對象的建立和管理等等,但實際上項目中引入Spring後,咱們無需本身去建立對象,而是交由Spring建立和管理,控制反轉具體來看,應該是控制對象的建立、管理等等,這些職責的反轉,原來是咱們的職責,如今反轉到了Spring容器那邊管理。另外說道IOC,每每還伴隨着一個DI(Dependency Injection)依賴注入的概念,前面爲何要在一個層的類中建立(獲取)另外一個類對象,是由於類與類之間的依賴,若是由咱們主動在類中建立對象,會使得項目高耦合,靈活度大大下降。而經過依賴注入可讓咱們輕鬆獲取由容器建立和管理的對象,而不須要在程序中硬編碼建立對象,從而達到解耦程序。依賴注入,基於Java反射,是控制反轉的一種具體實現方式。java
AOP(Aspect Oriented Programming)面向切面編程,使用到Java中代理模式,是對面向對象編程的一種補充,而不是競爭或衝突,例如咱們看待一段web項目訪問過程,首先訪問模塊A,隨之系統會記錄訪問日誌,而後訪問模塊B,系統也會隨之記錄訪問日誌,以面向對象的思惟來看,從前到後,這是兩段完整的過程,每段過程當中又包括咱們的訪問和系統的日誌記錄兩種操做。可是換到這裏的切面思惟,咱們每訪問一個模塊,系統都會隨之有記錄訪問日誌,把這個記錄日誌的動做以切面抽取並封裝起來,能夠減小系統的重複代碼,下降模塊之間的耦合度,提升系統的可操做性和可維護性。常見應用有例如事務管理、日誌管理、安全控制等等。mysql
既然Spring容器能幫助咱們建立和管理對象,那麼在這裏,不一樣於前面的獨立MyBatis程序,咱們能夠把那些獲取對象的過程按照Spring的方式作些修改。首先來回顧下前面咱們作MyBatis單獨測試的方法代碼,示例以下:web
@Test public void testCore() throws IOException { //直接實例SqlSessionFactoryBuilder對象 SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); //MyBatis配置文件路徑 String path = "mybatis-config.xml"; //經過路徑獲取輸入流 Reader reader = Resources.getResourceAsReader(path); //經過reader構建sessionFactory SqlSessionFactory sessionFactory = builder.build(reader); //獲取SqlSession對象 SqlSession sqlSession = sessionFactory.openSession(); //獲取Mapper實例 DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.selectById(10001); Company company = dept.getCompany(); //所屬公司 List<Emp> empList = dept.getEmpList(); //員工集合 System.out.println(dept); }
這裏的SqlSessionFactory、SqlSession、Mapper實例等對象都是由咱們手動去本身建立,下面正文開始經過Spring集成方式,咱們能夠免除這些建立對象的代碼。spring
數據庫環境MySql,工具Navicat for MySQL,建立一張Person表以下所示,並填入幾條測試數據sql
新建Maven項目,能夠是普通Jar項目,簡單選quickstart那個,工程結構以下所示:數據庫
POM依賴可參考SSM框架開發web項目系列(一) 環境搭建篇編程
package com.mmm.pojo; public class Person { private Integer id; //主鍵 private String name; //姓名 private String gender; //性別 private Integer age; //年齡 private String ifIT; //是否從事IT行業 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getIfIT() { return ifIT; } public void setIfIT(String ifIT) { this.ifIT = ifIT; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + ", gender=" + gender + ", age=" + age + ", ifIT=" + ifIT + "]"; } }
<?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> <!-- 這裏能夠定義類的別名,在mapper.xml文件中應用會方便不少 --> <typeAliases> <typeAlias alias="psn" type="com.mmm.pojo.Person" /> </typeAliases> <!-- 這裏的環境配置中事務管理器和數據源分別在Spring配置文件中去配置,因此本來這裏的部分就能夠不寫了 --> <!-- <environments default="envir"> <environment id="envir"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://192.168.0.100:3306/ssm?characterEncoding=utf-8"/> <property name="username" value="root"/> <property name="password" value="abc123"/> </dataSource> </environment> </environments> --> <!-- 經過在Spring集成MyBatis配置文件中SqlSessionFactoryBean中的mapperLocations屬性配置實現sql映射xml文件的掃描,因此下面的mappers在這裏也能夠不寫了--> <!-- <mappers> <mapper resource="com/mmm/mapper/personMapper.xml"/> </mappers> --> </configuration>
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <!-- 引入jdbc參數配置 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- Spring會自動掃描base-package指定包下面添加了@Component @Service等註解的類並將其實例化 --> <context:component-scan base-package="com.mmm" /> <!-- 配置數據源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- spring和MyBatis整合 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自動掃描mapping.xml文件 --> <property name="mapperLocations" value="classpath:com/mmm/mapper/*.xml"></property> <property name="configLocation" value="classpath:mybatis-config.xml"></property> </bean> <!-- DAO接口所在包名,Spring會自動查找其下的類 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.mmm.mapper" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!-- 配置事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- <bean id="personMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <property name="mapperInterface" value="com.mmm.mapper.PersonMapper" /> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean> --> </beans>
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/ssm
jdbc.username=root
jdbc.password=123456
package com.mmm.mapper; import java.util.List; import com.mmm.pojo.Person; public interface PersonMapper { //查找全部Person對象 List<Person> selectAll(); }
<?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.mmm.mapper.PersonMapper"> <resultMap type="psn" id="personResultMap"> <id column="ID" property="id" /> <result column="NAME" property="name" /> <result column="GENDER" property="gender" /> <result column="AGE" property="age" /> <result column="IF_IT" property="ifIT" /> </resultMap> <select id="selectAll" resultMap="personResultMap"> select * from person </select> </mapper>
最後咱們的測試方法就不用像以前那樣建立一連串的對象,能夠經過以下方式:安全
package com.mmm.test; import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mmm.mapper.PersonMapper; import com.mmm.pojo.Person; public class TestSpringMbs { @SuppressWarnings("resource") @Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("application-root.xml"); PersonMapper personMapper = (PersonMapper) context.getBean("personMapper"); List<Person> list = personMapper.selectAll(); for(Person p:list) { System.out.println(p); } } }
最後運行一下測試方法,能夠看到以下結果,獲取到數據庫Person表所有記錄,即成功運行session
這裏經過Spring集成MyBatis的一個很基礎的示例,咱們能對Spring集成ORM框架的大體過程有個基本認識,不只僅是MyBatis,相似Hibernate、JPA那塊在Spring集成過程當中核心步驟大體也包涵了本文中的部分。框架會變,可是有些系統的硬性需求不會變,就比如這裏的持久層,你要訪問數據庫,不管你用MyBatis,仍是Hibernate,甚至是原生的JDBC,數據庫的訪問帳號密碼,只不過一步步封裝到了框架中的數據源;咱們的更新提交回退等等,在框架中演化成事務管理。理清這些硬性需求並跟隨者去學習,每每能更順暢的記住和理解。而不是說你學了半天MyBatis,以爲數據庫操做什麼都沒問題了,而後忽然換個Hibernate,感受一片迷茫,認清這些核心的概念,每每能幫助咱們快速的觸類旁通學習新知識。