Java EE學習筆記(十)

MyBatis與Spring的整合

一、整合環境搭建 

1)、要實現MyBatis與Spring的整合,很明顯須要這兩個框架的JAR包,可是隻使用這兩個框架中所提供的JAR包是不夠的,還須要其餘的JAR包來配合使用,整合時所需準備的JAR包具體以下。Spring框架所需的JAR包java

注意:核心容器依賴的commons-logging的JAR在MyBatis框架的lib包中已經包含mysql

2)、MyBatis框架所需的JAR包:(共13個)spring

3)、MyBatis與Spring整合的中間JAR:mybatis-spring-1.3.1.jarsql

4)、數據庫驅動JAR(MySQL):mysql-connector-java-5.1.40-bin.jar數據庫

5)、數據源所需JAR(DBCP數據庫鏈接池):commons-dbcp2-2.1.1.jar、commons-pool2-2.4.2.jarapache

6)、編寫配置文件:編程

①建立項目,引入JAR包;mybatis

②編寫db.properties ;app

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis
jdbc.username=root
jdbc.password=******
jdbc.maxTotal=30
jdbc.maxIdle=10
jdbc.initialSize=5框架

#密碼本身設置

編寫Spring配置文件applicationContext.xml;

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 4     xmlns:aop="http://www.springframework.org/schema/aop"
 5     xmlns:tx="http://www.springframework.org/schema/tx" 
 6     xmlns:context="http://www.springframework.org/schema/context"
 7     xsi:schemaLocation="http://www.springframework.org/schema/beans 
 8     http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 9     http://www.springframework.org/schema/tx 
10     http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
11     http://www.springframework.org/schema/context 
12     http://www.springframework.org/schema/context/spring-context-4.3.xsd
13     http://www.springframework.org/schema/aop 
14     http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
15     
16     <!--一、讀取db.properties文件的位置 -->
17     <context:property-placeholder location="classpath:db.properties"/>
18     
19     <!-- 二、配置數據源 -->
20     <bean id="dataSourceID" class="org.apache.commons.dbcp2.BasicDataSource">
21     
22         <!--2.一、數據庫驅動 -->
23         <property name="driverClassName" value="${jdbc.driver}" />
24         
25         <!--2.二、鏈接數據庫的url -->
26         <property name="url" value="${jdbc.url}" />
27         
28         <!--2.三、鏈接數據庫的用戶名 -->
29         <property name="username" value="${jdbc.username}" />
30         
31         <!--2.四、鏈接數據庫的密碼 -->
32         <property name="password" value="${jdbc.password}" />
33         
34         <!--2.五、最大鏈接數 -->
35         <property name="maxTotal" value="${jdbc.maxTotal}" />
36         
37         <!--2.六、最大空閒鏈接  -->
38         <property name="maxIdle" value="${jdbc.maxIdle}" />
39         
40         <!--2.七、初始化鏈接數  -->
41         <property name="initialSize" value="${jdbc.initialSize}" />
42         
43     </bean>
44     
45     <!-- 三、事務管理器,依賴於數據源 --> 
46     <bean id="transactionManagerID" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
47         <property name="dataSource" ref="dataSourceID" />
48     </bean>    
49     
50     <!--四、開啓事務註解 -->
51     <tx:annotation-driven transaction-manager="transactionManagerID"/>
52     
53     <!--五、配置MyBatis工廠來於Spring整合,
54         構建sqlSessionFactory是經過mybatis.spring包中提供的org.mybatis.spring.SqlSessionFactoryBean類配置的;
55         配置時一般須要2個參數:①數據源;②MyBatis的配置文件路徑
56      -->
57     <bean id="sqlSessionFactoryID" class="org.mybatis.spring.SqlSessionFactoryBean">
58          
59          <!--5.一、注入數據源 -->
60          <property name="dataSource" ref="dataSourceID" />
61          
62          <!--5.二、指定核心配置文件位置 :mybatis-config.xml-->
63            <property name="configLocation" value="classpath:mybatis-config.xml"/>
64            
65    </bean>
66    
67    <!--六、實例化Dao -->
68     <bean id="customerDaoID" class="com.itheima.dao.impl.CustomerDaoImpl">
69     <!-- 6.一、注入SqlSessionFactory對象實例-->
70          <property name="sqlSessionFactory" ref="sqlSessionFactoryID" />
71     </bean>
72     
73     <!-- 七、Mapper代理開發(基於MapperFactoryBean) -->
74     <!-- <bean id="customerMapperID" class="org.mybatis.spring.mapper.MapperFactoryBean">
75         
76         指定了接口mapperInterface和工廠sqlSessionFactory
77         <property name="mapperInterface" value="com.itheima.mapper.CustomerMapper" />
78         <property name="sqlSessionFactory" ref="sqlSessionFactoryID" />  
79         
80     </bean> -->
81     
82     <!-- 八、Mapper代理開發(基於MapperScannerConfigurer)
83         配置類路徑:org.mybatis.spring.mapper.MapperScannerConfigurer
84         指定映射文件所在的包路徑:com.itheima.mapper
85      -->
86     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
87          <property name="basePackage" value="com.itheima.mapper" />
88     </bean>
89     
90     <!-- 九、使用註解,開啓掃描
91         Spring註解提供了另一種高效的註解配置方式,(對包路徑下的全部Bean文件進行掃描) 
92         使用 context 命名空間 ,通知Spring掃描指定包下全部Bean類,進行註解解析  
93      --> 
94     <context:component-scan base-package="com.itheima.service" />
95     
96 </beans>

編寫MyBatis配置文件mybatis-config.xml;

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 3                         "http://mybatis.org/dtd/mybatis-3-config.dtd">
 4 <configuration>
 5 
 6     <!--一、配置別名:POJO類過多時,使用自動掃描包的形式定義別名 
 7         目的:在於減小全限定類名的冗餘。
 8     -->
 9     <typeAliases>
10         <package name="com.itheima.po" />
11     </typeAliases>
12    
13     <!--二、配置Mapper的位置 -->
14     <mappers> 
15        
16        <mapper resource="com/itheima/po/CustomerMapper.xml" />
17        
18        <!-- Mapper接口開發方式 -->
19        <mapper resource="com/itheima/mapper/CustomerMapper.xml" />
20        
21     </mappers>
22 </configuration>

引入log4j.properties。

# Global logging configuration
log4j.rootLogger=ERROR, stdout

# MyBatis logging configuration...
log4j.logger.com.itheima=DEBUG

# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

二、傳統DAO方式的開發整合

1)、採用傳統DAO開發方式進行MyBatis與Spring框架的整合時,可使用mybatis-spring包中所提供的SqlSessionTemplate類SqlSessionDaoSupport類來實現。

 2)、SqlSessionTemplate:是mybatis-spring的核心類,它負責管理MyBatis的SqlSession(會話對象)調用MyBatis的SQL方法。當調用SQL方法時,SqlSessionTemplate將會保證使用的SqlSession和當前Spring的事務是相關的。它還管理SqlSession的生命週期,包含必要的關閉、提交和回滾操做

3)、SqlSessionDaoSupport:是一個抽象支持類,它繼承DaoSupport類,主要是做爲DAO的基類來使用。能夠經過SqlSessionDaoSupport類的getSqlSession()方法來獲取所需的SqlSession
4)、實現持久層:

①客戶持久化類:src/com/itheima/po/Customer.java

 1 package com.itheima.po;
 2 /**
 3  * 客戶持久化類
 4  */
 5 public class Customer {
 6     private Integer id;       // 主鍵id
 7     private String username; // 客戶名稱
 8     private String jobs;      // 職業
 9     private String phone;     // 電話
10     
11     public Integer getId() {
12         return id;
13     }
14     
15     public void setId(Integer id) {
16         this.id = id;
17     }
18     
19     public String getUsername() {
20         return username;
21     }
22     
23     public void setUsername(String username) {
24         this.username = username;
25     }
26     
27     public String getJobs() {
28         return jobs;
29     }
30     
31     public void setJobs(String jobs) {
32         this.jobs = jobs;
33     }
34     
35     public String getPhone() {
36         return phone;
37     }
38     
39     public void setPhone(String phone) {
40         this.phone = phone;
41     }
42     
43     @Override
44     public String toString() {
45         return "Customer [id=" + id + ", username=" + username + ", jobs=" + jobs + ", phone=" + phone + "]";
46     }
47 }

②建立客戶映射(映射數據庫表)文件:src/com/itheima/po/CustomerMapper.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 3                     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 4                     
 5 <mapper namespace="com.itheima.po.CustomerMapper">
 6     
 7     <!--根據id查詢客戶信息 -->
 8     <select id="findCustomerById" parameterType="Integer"
 9              resultType="customer">
10         <!-- 屬性resultType:用於指定返回結果的類型,這裏表示返回的數據是customer對象類型,
11             可見,其直接使用了別名,減小全限定名稱的冗餘。    
12             至關於把 com.itheima.po.Customer 換成了customer
13          -->
14         select * from t_customer where id = #{id}
15     </select>
16 </mapper>

 ③在MyBatis的配置文件mybatis-config.xml中,配置映射文件src/com/itheima/po/CustomerMapper.xml

<mapper resource="com/itheima/po/CustomerMapper.xml" />

5)、實現DAO層

①建立Dao的接口:CustomerDao

package com.itheima.dao;
import com.itheima.po.Customer;

public interface CustomerDao {
    // 經過id查詢客戶
    public Customer findCustomerById(Integer id);
}

②建立接口CustomerDao的實現類:src/com/itheima/dao/impl/CustomerDaoImpl.java

 1 package com.itheima.dao.impl;
 2 import org.mybatis.spring.support.SqlSessionDaoSupport;
 3 import com.itheima.dao.CustomerDao;
 4 import com.itheima.po.Customer;
 5 
 6 
 7 /* CustomerDaoImpl類繼承了SqlSessionDaoSupport類,並實現了CustomerDao接口。
 8  * 其中SqlSessionDaoSupport類在使用時須要一個SqlSessionFactory或一個SqlSessionTemplate對象
 9  * 因此須要Spring給SqlSessionDaoSupport類的子類對象注入一個SqlSessionFactory或SqlSessionTemplate。
10  * 這樣子類中就能經過調用SqlSessionDaoSupport類的getSqlSession()方法來獲取SqlSession對象,並使用SqlSession對象中的方法。
11  *  
12  */
13 
14 public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao {
15     // 經過id查詢客戶
16     public Customer findCustomerById(Integer id) {
17          return this.getSqlSession().selectOne("com.itheima.po.CustomerMapper.findCustomerById", id);
18     }
19 }

③整合測試:src/com/itheima/test/DaoTest.java

 1 package com.itheima.test;
 2 import org.junit.Test;
 3 import org.springframework.context.ApplicationContext;
 4 import 
 5      org.springframework.context.support.ClassPathXmlApplicationContext;
 6 import com.itheima.dao.CustomerDao;
 7 import com.itheima.mapper.CustomerMapper;
 8 import com.itheima.po.Customer;
 9 /**
10  * DAO測試類
11  */
12 public class DaoTest {
13     @Test
14     public void findCustomerByIdDaoTest(){
15         ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
16           // 根據容器中Bean的id來獲取指定的Bean
17 //         CustomerDao customerDao = (CustomerDao) act.getBean("customerDaoID");
18          
19          //Spring獲取Bean的另外一種方式,這種方式再也不須要進行強制類型轉換了
20          CustomerDao customerDao = act.getBean(CustomerDao.class); 
21          Customer customer = customerDao.findCustomerById(1);
22          System.out.println(customer);
23     }
24 }

④測試結果:

三、Mapper接口方式的開發整合

1)、在MyBatis+Spring的項目中,雖然使用傳統的DAO開發方式能夠實現所需功能,可是採用這種方式在實現類中會出現大量的重複代碼在方法中也須要指定映射文件中執行語句的id,而且不能保證編寫時id的正確性(運行時才能知道)。爲此,咱們可使用MyBatis提供的另一種編程方式,即使用Mapper接口編程

2)、基於MapperFactoryBean的整合

a)、MapperFactoryBean是MyBatis-Spring團隊提供的一個用於根據Mapper接口生成Mapper對象的類,該類在Spring配置文件中使用時能夠配置如下參數:

mapperInterface:用於指定接口
SqlSessionFactory:用於指定SqlSessionFactory
SqlSessionTemplate:用於指定SqlSessionTemplate。若是與SqlSessionFactory同時設定,則只會啓用SqlSessionTemplate

b)、實操MapperFactoryBean是如何來實現MyBatis與Spring的整合:

建立CustomerMapper接口即對應的映射文件:(注意此處就與上面的操做不一樣了)src/com/itheima/mapper--->CustomerMapper.java

 1 package com.itheima.mapper;
 2 
 3 import java.lang.Integer;
 4 import com.itheima.po.Customer;
 5 public interface CustomerMapper { // 建立CustomerMapper接口
 6     
 7     // 經過id查詢客戶
 8     public Customer findCustomerById(Integer id);
 9     
10     // 添加客戶
11     public void addCustomer(Customer customer);
12 
13 }

②src/com/itheima/mapper--->CustomerMapper.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 3                 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 4             
 5 <mapper namespace="com.itheima.mapper.CustomerMapper">
 6     
 7     <!--一、根據id查詢客戶信息,返回類型是customer類型
 8         Mapper接口中的方法名和Mapper.xml中定義的每一個執行語句的id相同!!!
 9      -->
10     <select id="findCustomerById" parameterType="Integer"
11              resultType="customer">
12         select * from t_customer where id = #{id}
13     </select>
14     
15     <!--二、添加客戶信息,參數類型是 customer類型-->
16     <insert id="addCustomer" parameterType="customer">
17         insert into t_customer(username,jobs,phone)
18         values(#{username},#{jobs},#{phone})
19     </insert>
20     
21 </mapper>

③在MyBatis的配置文件mybatis-config.xml中,配置新的映射文件src/com/itheima/mapper/CustomerMapper.xml

<mapper resource="com/itheima/mapper/CustomerMapper.xml" />

④在Spring的配置文件中,建立CustomerMapper的Bean實例id

   <!-- 七、Mapper代理開發(基於MapperFactoryBean) -->
    <bean id="customerMapperID" class="org.mybatis.spring.mapper.MapperFactoryBean">
        
        <!-- 指定了接口mapperInterface和工廠sqlSessionFactory -->
        <property name="mapperInterface" value="com.itheima.mapper.CustomerMapper" />
        <property name="sqlSessionFactory" ref="sqlSessionFactoryID" />  
        
    </bean>

⑤單元測試:

    @Test
    public void findCustomerByIdMapperTest(){    
        ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
        CustomerMapper customerMapper = act.getBean(CustomerMapper.class);   
        Customer customer = customerMapper.findCustomerById(1);
        System.out.println(customer);
    }

⑥測試結果:

c)、Mapper接口編程方式只須要編寫Mapper接口至關於DAO接口),而後由MyBatis框架根據接口的定義建立接口的動態代理對象,等同於DAO接口的實現類

3)、雖然使用Mapper接口編程的方式很簡單,可是在具體使用時仍是須要遵循一些規範。

a)、Mapper接口的名稱對應的Mapper.xml映射文件的名稱必須一致

b)、Mapper.xml文件中的namespaceMapper接口類路徑相同。(即接口文件和映射文件須要放在同一個包中

c)、注意:Mapper接口中的方法名和Mapper.xml中定義的每一個執行語句的id相同

d)、Mapper接口中方法的輸入參數類型要和Mapper.xml中定義的每一個sql的parameterType的類型相同。

e)、Mapper接口方法的輸出參數類型要和Mapper.xml中定義的每一個sql的resultType的類型相同。

4)、基於MapperScannerConfigurer的整合

a)、在實際的項目中,DAO層會包含不少接口,若是每個接口都在Spring配置文件中配置,不但會增長工做量,還會使得Spring配置文件很是臃腫。爲此,能夠採用自動掃描的形式來配置MyBatis中的映射器——採用MapperScannerConfigurer類

b)、MapperScannerConfigurer類在Spring配置文件中能夠配置如下屬性:

basePackage:指定映射接口文件所在的包路徑,當須要掃描多個包時可使用分號或逗號做爲分隔符。指定包路徑後,會掃描該包及其子包中的全部文件
annotationClass:指定了要掃描的註解名稱,只有被註解標識的類纔會被配置爲映射器
sqlSessionFactoryBeanName:指定在Spring中定義的SqlSessionFactory的Bean名稱。
sqlSessionTemplateBeanName:指定在Spring中定義的SqlSessionTemplate的Bean名稱。若是定義此屬性,則sqlSessionFactoryBeanName將不起做用。
markerInterface:指定建立映射器的接口

c)、MapperScannerConfigurer的使用很是簡單,只須要在Spring的配置文件中編寫以下代碼:

<!-- Mapper代理開發(基於MapperScannerConfigurer) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
     <property name="basePackage" value="com.itheima.mapper" />
</bean>

d)、一般狀況下,MapperScannerConfigurer在使用時只需經過basePackage屬性指定須要掃描的包便可,Spring會自動的經過包中的接口來生成映射器。這使得開發人員能夠在編寫不多代碼的狀況下,完成對映射器的配置,從而提升開發效率。對MapperScannerConfigurer進行測試可得與上面相同的結果。

四、 測試事務

1)、在項目中,Service層既是處理業務的地方,又是管理數據庫事務的地方。對事務進行測試:

a)、建立Service層

b)、在Service層編寫添加客戶操做的代碼

c)、有意地添加一段異常代碼(如int i = 1/0;)來模擬現實中的意外狀況

d)、編寫測試方法,調用業務層的添加方法。這樣,程序在執行到錯誤代碼時就會出現異常

2)、在沒有事務管理的狀況下,即便出現了異常,數據也會被存儲到數據表中;若是添加了事務管理,而且事務管理的配置正確,那麼在執行上述操做時,所添加的數據將不可以插入到數據表中

3)在CustomerMapper接口中,添加addCustomer()方法,而後在CustomerMapper映射文件中編寫執行插入操做的SQL配置,具體看上面的代碼。

①建立業務接口:src/com/itheima/service/CustomerService.java

package com.itheima.service;
import com.itheima.po.Customer;
public interface CustomerService { // 業務層:建立CustomerService接口
    public void addCustomer(Customer customer);
}

②建立業務接口的實現類:com/itheima/service/impl/CustomerServiceImpl.java

 1 package com.itheima.service.impl;
 2 import org.springframework.beans.factory.annotation.Autowired;
 3 import org.springframework.stereotype.Service;
 4 import org.springframework.transaction.annotation.Transactional;
 5 import com.itheima.mapper.CustomerMapper;
 6 import com.itheima.po.Customer;
 7 import com.itheima.service.CustomerService;
 8 
 9 // 使用Spring的註解@Service來標識業務層的類
10 @Service
11 
12 // 使用@Transactional註解來標識事務處理的類
13 @Transactional
14 public class CustomerServiceImpl implements CustomerService {
15     
16     //經過@Autowired註解注入CustomerMapper
17     @Autowired
18     private CustomerMapper customerMapper;
19     
20     //添加客戶
21     public void addCustomer(Customer customer) {
22         // 調用接口中的addCustomer()方法
23         this.customerMapper.addCustomer(customer);
24         
25         //模擬添加操做後系統忽然出現的異常問題
26         int i = 1 / 0; 
27     }
28 }

③在Spring的配置文件中,編寫開啓註解掃描的配置代碼:

   <!-- 九、使用註解,開啓掃描
        Spring註解提供了另一種高效的註解配置方式,(對包路徑下的全部Bean文件進行掃描) 
        使用 context 命名空間 ,通知Spring掃描指定包下全部Bean類,進行註解解析  
     --> 
    <context:component-scan base-package="com.itheima.service" />

④測試類:com/itheima/test/TransactionTest.java

 1 package com.itheima.test;
 2 import org.springframework.context.ApplicationContext;
 3 import org.springframework.context.support.ClassPathXmlApplicationContext;
 4 import com.itheima.po.Customer;
 5 import com.itheima.service.CustomerService;
 6 /**
 7  * 測試事務
 8  */
 9 public class TransactionTest {
10     public static void main(String[] args) {
11         ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext.xml");
12         CustomerService customerService = act.getBean(CustomerService.class);
13         
14         Customer customer = new Customer();
15         customer.setUsername("zhangsan");
16         customer.setJobs("manager");
17         customer.setPhone("13233334444");
18         customerService.addCustomer(customer);
19     }
20 }

⑤先將@Transactional註釋掉後運行測試類的結果以下:

4)、雖拋出異常,但查詢數據庫mybatis中的t_customer表可知,新添加的數據已經存儲在該表中,這就驗證了在沒有事務管理的狀況下,即便出現了異常,數據也會被存儲到數據表中

5)、將註釋去掉,再次執行並查詢表如圖所示:

 

這就說明項目中配置的事務是正確的。

我的總結:

本章詳細介紹瞭如何實現SM的整合步驟。我的認爲基於Mapper的接口方式實現MyBatis與Spring的整合是相對比較方便和簡單的,至少在編碼方面能提升開發者的工做效率,但實現DAO層的整合也需充分理解,總之,實踐是檢驗真知的標準!

相關文章
相關標籤/搜索