1. 程式人生 > >spring整合mybatis的事務管理

spring整合mybatis的事務管理

<pre name="code" class="html"><?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.yihaomen.mybatis.inter.UserMapper">

	<select id="selectUserByID" parameterType="int" resultType="User">
	    select * from `user` where id = #{id}
	</select>
	
	<!-- 為了返回list 型別而定義的returnMap -->
	<resultMap type="User" id="resultListUser">
        <id column="id" property="id" />
        <result column="userName" property="userName" />
        <result column="userAge" property="userAge" />
        <result column="userAddress" property="userAddress" />
    </resultMap>
	
	<!-- 返回list 的select 語句,注意 resultMap 的值是指向前面定義好的 -->
	<select id="selectUsers" parameterType="string" resultMap="resultListUser">
	    select * from user where userName like #{userName}
	</select>
	
	
	
	<!-- User 聯合文章進行查詢 方法之一的配置 (多對一的方式)  -->	
	<resultMap id="resultUserArticleList" type="Article">
	    <id property="id" column="aid" />
	    <result property="title" column="title" />
	    <result property="content" column="content" />
	    
	    <association property="user" javaType="User">
	        <id property="id" column="id" />
	        <result property="userName" column="userName" />
	        <result property="userAddress" column="userAddress" />	        
	    </association>	    
	</resultMap>
	
	<!-- User 聯合文章進行查詢 方法之二的配置 (多對一的方式) -->	
	<resultMap id="resultUserArticleList-2" type="Article">
	    <id property="id" column="aid" />
	    <result property="title" column="title" />
	    <result property="content" column="content" />	    
	    <association property="user" javaType="User" resultMap="resultListUser" />	         
	</resultMap>
	
	<select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
	   select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article 
	          where user.id=article.userid and user.id=#{id}
	</select>
	
	
	<!--執行增加操作的SQL語句。id和parameterType  
       分別與IUserOperation介面中的addUser方法的名字和  
       引數型別一致。以#{name}的形式引用Student引數  
       的name屬性,MyBatis將使用反射讀取Student引數  
       的此屬性。#{name}中name大小寫敏感。引用其他  
       的gender等屬性與此一致。seGeneratedKeys設定  
       為"true"表明要MyBatis獲取由資料庫自動生成的主  
       鍵;keyProperty="id"指定把獲取到的主鍵值注入  
       到Student的id屬性--> 
    <insert id="addUser" parameterType="User" 
        useGeneratedKeys="true" keyProperty="id"> 
        insert into user(userName,userAge,userAddress)  
             values(#{userName},#{userAge},#{userAddress})  
    </insert>
    
    <update id="updateUser" parameterType="User" >
        update user set userName=#{userName},userAge=#{userAge},userAddress=#{userAddress} where id=#{id}
    </update>
    
    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
</mapper>

整體的spring配置檔案,application.xml如下:
<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="  
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd  
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
	default-autowire="byName" default-lazy-init="false">

	<!--本示例採用DBCP連線池,應預先把DBCP的jar包複製到工程的lib目錄下。 -->

	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url"
			value="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8" />
		<property name="username" value="root" />
		<property name="password" value="123456" />
	</bean>

	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<!--dataSource屬性指定要用到的連線池 -->
		<property name="dataSource" ref="dataSource" />
		<!--configLocation屬性指定mybatis的核心配置檔案 -->
		<property name="configLocation" value="config/Configuration.xml" />
	</bean>
	
	<!-- 開啟註解配置 -->
	<context:annotation-config />

	<context:component-scan base-package="com.yihaomen.test" />

	<bean name="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>

	<!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.yihaomen.mybatis.inter" />
	</bean> -->
	
	<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
     <!--sqlSessionFactory屬性指定要用到的SqlSessionFactory例項--> 
     <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
     <!--mapperInterface屬性指定對映器介面,用於實現此介面並生成對映器物件--> 
     <property name="mapperInterface" value="com.yihaomen.mybatis.inter.UserMapper" /> 
  </bean> 
	
	<!-- 使用annotation定義事務 -->
	<tx:annotation-driven proxy-target-class="true"/>
	
</beans> 

首先,配置資料來源dataSource。這裡採用dbpc連線池來管理資料來源

然後配置sqlSessionFactory,sql會話工廠需要注入資料來源、mybatis的配置xml檔案

下面是mybatis的配置檔案,Configuration.xml

<?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>
    <typeAliases> 
        <typeAlias alias="User" type="com.yihaomen.mybatis.model.User"/> 
        <typeAlias alias="Article" type="com.yihaomen.mybatis.model.Article"/> 
    </typeAliases> 
    <!-- 與spring 整合之後,這些可以完全刪除,資料庫連線的管理交給 spring 去管理 -->
	<!--  <environments default="development">
		<environment id="development">
		<transactionManager type="JDBC"/>
			<dataSource type="POOLED">
			<property name="driver" value="com.mysql.jdbc.Driver"/>
			<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf8" />
			<property name="username" value="root"/>
			<property name="password" value="password"/>
			</dataSource>
		</environment>
	</environments>
	-->	 
	<mappers>
	    <mapper resource="com/yihaomen/mybatis/model/User.xml"/>
	</mappers>
</configuration>
這個檔案裡主要聲明瞭兩個對映表的實體類和一個mapper資原始檔的位置。

我們在配置檔案裡給這兩個實體類分別起了別名,那麼在後續的返回值型別上我們就可以直接引用別名了,而不是寫包名.類名。

這個mapper資原始檔中定義了sql語句,以及名稱空間。

下面是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.yihaomen.mybatis.inter.UserMapper">

	<select id="selectUserByID" parameterType="int" resultType="User">
	    select * from `user` where id = #{id}
	</select>
	
	<!-- 為了返回list 型別而定義的returnMap -->
	<resultMap type="User" id="resultListUser">
        <id column="id" property="id" />
        <result column="userName" property="userName" />
        <result column="userAge" property="userAge" />
        <result column="userAddress" property="userAddress" />
    </resultMap>
	
	<!-- 返回list 的select 語句,注意 resultMap 的值是指向前面定義好的 -->
	<select id="selectUsers" parameterType="string" resultMap="resultListUser">
	    select * from user where userName like #{userName}
	</select>
	
	
	
	<!-- User 聯合文章進行查詢 方法之一的配置 (多對一的方式)  -->	
	<resultMap id="resultUserArticleList" type="Article">
	    <id property="id" column="aid" />
	    <result property="title" column="title" />
	    <result property="content" column="content" />
	    
	    <association property="user" javaType="User">
	        <id property="id" column="id" />
	        <result property="userName" column="userName" />
	        <result property="userAddress" column="userAddress" />	        
	    </association>	    
	</resultMap>
	
	<!-- User 聯合文章進行查詢 方法之二的配置 (多對一的方式) -->	
	<resultMap id="resultUserArticleList-2" type="Article">
	    <id property="id" column="aid" />
	    <result property="title" column="title" />
	    <result property="content" column="content" />	    
	    <association property="user" javaType="User" resultMap="resultListUser" />	         
	</resultMap>
	
	<select id="getUserArticles" parameterType="int" resultMap="resultUserArticleList">
	   select user.id,user.userName,user.userAddress,article.id aid,article.title,article.content from user,article 
	          where user.id=article.userid and user.id=#{id}
	</select>
	
	
	<!--執行增加操作的SQL語句。id和parameterType  
       分別與IUserOperation介面中的addUser方法的名字和  
       引數型別一致。以#{name}的形式引用Student引數  
       的name屬性,MyBatis將使用反射讀取Student引數  
       的此屬性。#{name}中name大小寫敏感。引用其他  
       的gender等屬性與此一致。seGeneratedKeys設定  
       為"true"表明要MyBatis獲取由資料庫自動生成的主  
       鍵;keyProperty="id"指定把獲取到的主鍵值注入  
       到Student的id屬性--> 
    <insert id="addUser" parameterType="User" 
        useGeneratedKeys="true" keyProperty="id"> 
        insert into user(userName,userAge,userAddress)  
             values(#{userName},#{userAge},#{userAddress})  
    </insert>
    
    <update id="updateUser" parameterType="User" >
        update user set userName=#{userName},userAge=#{userAge},userAddress=#{userAddress} where id=#{id}
    </update>
    
    <delete id="deleteUser" parameterType="int">
        delete from user where id=#{id}
    </delete>
    
</mapper>
這裡我們介紹一種比較方便的查詢方法,介面式查詢。

首先我們定義一個介面,包名.類名和mapper的namespace屬性相同,裡面定義一些增刪改查的方法,方法名要和mapper中的sql語句的id相同,這樣我們就可以使用介面式方法來做資料庫操作了。

下面是介面的程式碼

package com.yihaomen.mybatis.inter;

import java.util.List;

import com.yihaomen.mybatis.model.*;

public interface UserMapper {
    
	public User selectUserByID(int id);
	public List<User> selectUsers(String userName);	
	public void addUser(User user);
	public void updateUser(User user);
	public void deleteUser(int id);
	
	public List<Article> getUserArticles(int id);
	
}
下面是呼叫方法:
package com.yihaomen.test;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.yihaomen.mybatis.inter.UserMapper;
import com.yihaomen.mybatis.model.Article;
import com.yihaomen.mybatis.model.User;

@Service("mybatisSprintTest")
public class MybatisSprintTest{

	@Autowired
	private UserMapper mapper;
	
	@Transactional(propagation = Propagation.REQUIRED)
	public void insert() {
		// 測試id=1的使用者查詢,根據資料庫中的情況,可以改成你自己的.
		System.out.println("得到使用者id=1的使用者資訊");
		System.out.println(mapper);
		
		User user = mapper.selectUserByID(1);
		System.out.println(user.getUserAddress());

		// 得到文章列表測試
		System.out.println("得到使用者id為1的所有文章列表");
		List<Article> articles = mapper.getUserArticles(1);

		for (Article article : articles) {
			System.out.println(article.getContent() + "--" + article.getTitle());
		}

		User newUser = new User();
		newUser.setUserAddress("a");
		newUser.setUserAge(5);
		newUser.setUserName("zhangyang");
		// 插入使用者
		mapper.addUser(newUser);
		// 插入後返回自增長ID
		System.out.println(newUser.getId()+"insert success");
		// 插入使用者
		mapper.addUser(newUser);
		// 插入後返回自增長ID
		System.out.println(newUser.getId()+"insert success");
		// 丟擲異常,@Transactional做事務回滾(兩條資料都不會插入)
		throwException();
	}

	private static void throwException() {
		throw new RuntimeException();
	}

	public UserMapper getMapper() {
		return mapper;
	}

	public void setMapper(UserMapper mapper) {
		this.mapper = mapper;
	}
	
}
首先我們需要用spring注入mapper屬性,檢視spring配置檔案中這段配置
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
     <!--sqlSessionFactory屬性指定要用到的SqlSessionFactory例項--> 
     <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
     <!--mapperInterface屬性指定對映器介面,用於實現此介面並生成對映器物件--> 
     <property name="mapperInterface" value="com.yihaomen.mybatis.inter.UserMapper" /> 
  </bean> 
這裡配置了一個mapper工廠,用於生產一個com.yihaomen.mybatis.inter.UserMapper的實現類,這個實現類實現了介面中定義的方法。

這裡應該使用的是proxy動態代理技術,用一個類來實現該介面,然後根據介面的包名.類名(名稱空間)+方法名(sql的id)去xml檔案中獲取對應的sql語句,

之後我們呼叫這個實現類的方法,傳入引數後獲取查詢結果。

到此就結束了。本文中的配置已經實現了業務層的事務管理,可以做到業務層事務回滾。

另外推薦一篇很好的帖子:http://blog.csdn.net/kutejava/article/details/9164353#t4

裡面講的mybatis很詳細,全部掌握後就是mybatis的大神了。

本工程程式碼在我的資原始檔裡有上傳,下載後匯入即可執行。環境:tomcat7,jdk7