Spring+MongoDB 4.0

主要是用于spring和MongoDB关于事务的整合,自己整合的,如果觉得有问题的地方,欢迎指出来

相关的jar包:

 <properties>
	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	<!-- spring -->
	<spring.version>5.0.4.RELEASE</spring.version>
	<junit.version>4.12</junit.version>
	<!-- 数据库相关 -->
	<mybatis_spring_version>1.2.3</mybatis_spring_version>
	<mybatis_version>3.4.1</mybatis_version>
	<mysql_connector_version>5.1.26</mysql_connector_version>
</properties>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-aspects</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-mongodb</artifactId>
	<version>2.0.8.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>3.8.0</version>
</dependency>

注入spring   MongoConfig.java

package com.tree.common.config;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.ClientSession;
import com.mongodb.client.MongoDatabase;

/**  
* @ClassName: MongoConfig  
* @Description: mongodb配置  注入spring
* @author chen shihua
* @date 2018年7月10日 下午1:35:00 
* @version V1.0  
*/
@Configuration
@EnableMongoRepositories("mongodb.properties")
public class MongoConfig {
	 private static Logger LOGGER = LoggerFactory.getLogger(MongoConfig.class);
	    
	    /**
	    * @Fields host : 服务器ip
	    */
	    @Value("${mongo.host}")
	    private String hostports;
	    
	    /**
	    * @Fields port : 端口号
	    */
	    @Value("${mongo.port}")
	    private String port;
	    
	    /**
	    * @Fields maxConnect : 一个线程变为可用的最大阻塞数  
	    */
	    @Value("${mongo.connectionsPerHost}")
	    private Integer connectionsPerHost;
	    
	    /**
	    * @Fields maxWaitThread : 线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值
	    */
	    @Value("${mongo.maxWaitThread}")
	    private Integer maxWaitThread;
	    
	    /**
	    * @Fields maxTimeOut : 连接超时时间(毫秒) 
	    */
	    @Value("${mongo.connectTimeout}")
	    private Integer connectTimeout;
	    
	    /**
	    * @Fields maxWaitTime : 最大等待时间 
	    */
	    @Value("${mongo.maxWaitTime}")
	    private Integer maxWaitTime;
	    
	    /**
	    * @Fields socketTimeout : scoket超时时间  
	    */
	    @Value("${mongo.socketTimeout}")
	    private Integer socketTimeout;
	    
	    /**
	    * @Fields username : 用户名
	    */
	    @Value("${mongo.username}")
	    private String username;
	    
	    /**
	    * @Fields password : 密码 
	    */
	    @Value("${mongo.password}")
	    private String password;
	    
	    /**
	    * @Fields database : 数据库
	    */
	    @Value("${mongo.database}")
	    private String database;
	    
	    /**
	    * @Fields collection : TODO(用一句话描述这个变量表示什么)  
	    */
	    @Value("${mongo.collection}")
	    private String collection;
	    
	    @Bean
	    public MongoClient mongoClient() {
	        MongoClient mongoClient = null;
	        
	        MongoClientOptions.Builder build = new MongoClientOptions.Builder();  
	        build.connectionsPerHost(Integer.valueOf(connectionsPerHost));  
	        build.threadsAllowedToBlockForConnectionMultiplier(maxWaitThread);  
	        build.connectTimeout(Integer.valueOf(connectTimeout) * 1000);  
	        build.maxWaitTime(Integer.valueOf(maxWaitTime) * 1000);
	        build.socketTimeout(socketTimeout);
	        build.socketKeepAlive(true);
	        MongoClientOptions options = build.build();  
	        
	        try {
	            List<ServerAddress> addrs = new ArrayList<ServerAddress>();  
	            for (String hostport : hostports.split(", *")) {
	                if (StringUtils.isBlank(hostport)) {
	                    continue;
	                }
	                hostport = hostport.trim();
	                
	                ServerAddress serverAddress = new ServerAddress(hostport.split(":")[0],Integer.valueOf(hostport.split(":")[1]));
	                addrs.add(serverAddress);  
	            }
	              
	            MongoCredential credential = MongoCredential.createScramSha1Credential(username, database, password.toCharArray());  
	            
	            mongoClient = new MongoClient(addrs,credential, options); 
	            LOGGER.info("20-02 " + "" + " 10-03 " + "admin" + " mongodb客户端创建成功 " + "admin");
	        } catch (Exception e) {
	            LOGGER.info("20-02 " + "" + " 10-03 " + "admin" + " mongodb客户端创建失败 " + "admin");
	            e.printStackTrace();
	        }
	        return mongoClient;
	    }
	    
	    @Bean
	    public ClientSession clientSession(MongoClient mongoClient) {
	    	ClientSession clientSession = mongoClient.startSession();
	    	return clientSession;
		}
	    
	    @Bean
	    public MongoDatabase mongoDatabase(MongoClient mongoClient) {
	         MongoDatabase mongoDatabase = mongoClient.getDatabase(database);
	         return mongoDatabase;
	    }
	    
	    @Bean()
	    public MongoTemplate mongoTemplate(MongoClient mongoClient){
	    	MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, database);
	    	return mongoTemplate;
	    }
	    
//	    @Bean
//	    public MongoCollection<Document> mongoCollection(MongoDatabase mongoDatabase) {
//	        MongoCollection<Document> mongoCollection = mongoDatabase.getCollection(collection);
//	        return mongoCollection;
//	    }
//	    
	    
}

数据库连接资源文件 mongodb.properties

#mongoDB连接配置
mongo.host=127.0.0.1
mongo.port=27017
mongo.username=name
mongo.password=123456
mongo.database=db
#一个线程变为可用的最大阻塞数
mongo.connectionsPerHost=8
#线程队列数,它以上面connectionsPerHost值相乘的结果就是线程队列最大值
mongo.maxWaitThread=4
#连接超时时间(毫秒)
mongo.connectTimeout=10000
#最大等待时间
mongo.maxWaitTime=1500
#自动重连
mongo.autoConnectRetry=true
#scoket保持活动
mongo.socketKeepAlive= true
#scoket超时时间
mongo.socketTimeout=1500
#读写分离
mongo.slaveOk=true

数据操作工具类 MongoSupport.java

package com.tree.common.config;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSONObject;
import com.mongodb.MongoSocketReadTimeoutException;
import com.mongodb.client.ClientSession;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.tree.common.templete.Pager;
import com.tree.common.util.MapUtils;
import com.tree.common.util.SpringUtil;

/**  
* @ClassName: MongoSupport  
* @Description: mongoDB 数据交互支持
* @author chen shihua
* @date 2018年7月10日 下午5:31:49 
* @version V1.0
* @param <T>  
*/
public class MongoSupport<T> {

	/**
	* @Fields mongoDatabase : 数据库对象
	*/
	private MongoDatabase mongoDatabase;
	
	/**
	* @Fields mongoCollection : 表集合对象
	*/
	private MongoCollection<Document> mongoCollection = null;
	
	/**
	* @Fields clazz : 泛型类 
	*/
	private final Class<T> clazz;
	
	MongoTemplate mongoTemplate;
	
	@SuppressWarnings("unchecked")
	public MongoSupport() {
		mongoDatabase = SpringUtil.getBean("mongoDatabase");
		mongoTemplate = SpringUtil.getBean("mongoTemplate");
		this.clazz = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		mongoCollection = mongoDatabase.getCollection(clazz.getSimpleName().toLowerCase());
	}
	
	/**  
	* @Title: selectAll  
	* @Description: 根据条件查询数据
	* @param query 查询对象  可以query.addCriteria(criteriaDefinition) 添加查询
	* @return List<T>   查询到的数据
	* @author chen shihua
	* @throws  
	*/
	public List<T> selectAll(Query query) {
		try {
			return mongoTemplate.find(query, this.clazz);
		} catch (MongoSocketReadTimeoutException e) {
			//连接超时,再进行一遍查询
			return mongoTemplate.find(query, this.clazz);
		}
		
	}
	
	/**  
	* @Title: selectCount  
	* @Description: 根据条件查询总条数
	* @param query 查询对象  可以query.addCriteria(criteriaDefinition) 添加查询
	* @return long   总条数
	* @author chen shihua
	* @throws  
	*/
	public long selectCount(Query query) {
		try {
			return mongoTemplate.count(query, this.clazz);
		} catch (MongoSocketReadTimeoutException e) {
			return mongoTemplate.count(query, this.clazz);
		}
		
	}

	/**  
	* @Title: selectPage  
	* @Description: 根据条件分页查询数据
	* @param page 分页对象
	* @param query 查询条件
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public void selectPage(Pager<T> page,Query query) {
		long count = this.selectCount(query);
		page.setTotal(count);
		int first = page.getFirst();
		int pageSize = page.getPageSize();
		query.skip(first).limit(pageSize);
		List<T> datas = new ArrayList<>();
		try {
			datas = this.selectAll(query);
		} catch (MongoSocketReadTimeoutException e) {
			datas = this.selectAll(query);
		}
		page.setData(datas);
	}
	
	/**  
	* @Title: seleceById  
	* @Description: 根据id查询数据
	* @param id  主键id
	* @return T    返回类型  
	* @author chen shihua
	* @throws  
	*/
	@SuppressWarnings("unchecked")
	public T seleceById(String id) {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		Document query = new Document("_id", new ObjectId(id));
		FindIterable<Document> iterable = null;
		try {
			iterable = (FindIterable<Document>) mongoCollection.find(clientSession, query, Document.class);
		} catch (MongoSocketReadTimeoutException e) {
			iterable = (FindIterable<Document>) mongoCollection.find(clientSession, query, Document.class);
		}

		MongoCursor<Document> cursor = iterable.iterator();

		List<Document> result = new ArrayList<Document>();

		while (cursor.hasNext()) {
			Document object = cursor.next();
			result.add(object);
		}
		if(CollectionUtils.isEmpty(result)) {
			return null;
		}
		Document document = result.get(0);
		String json = document.toJson();
	
		Map<String, Object> map = JSONObject.parseObject(json, Map.class);
		map.remove("_id");
		map.put("id", id);
		T t = (T) MapUtils.mapToObject(map, this.clazz);
		return t;
	}
	
	/**  
	* @Title: update  
	* @Description: 根据查询条件修改数据
	* @param query 查询条件
	* @param update 修改数据
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public void update(Map<String, Object> query, Map<String, Object> update) {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		Document queryDocument= new Document(query);
		Document modifiers = new Document();
		update.remove("id");
		Document updateDocument = new Document(update);
		modifiers.append("$set", updateDocument);
		try {
			mongoCollection.updateMany(clientSession, queryDocument, modifiers );
		} catch (MongoSocketReadTimeoutException e) {
			mongoCollection.updateMany(clientSession, queryDocument, modifiers );
		}
		
	}
	
	/**  
	* @Title: updateById  
	* @Description: 根据id修改数据
	* @param id 主键id
	* @param update 修改数据
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public void updateById(String id,Map<String, Object> update) {
		Map<String, Object> query = new HashMap<>();
		query.put("_id", new ObjectId(id));
		this.update(query , update);
	}
	
	/**  
	* @Title: insert  
	* @Description: 添加单条数据
	* @param entity 数据对象
	* @return void    返回类型  
	* @author chen shihua
	 * @throws Exception 
	* @throws  
	*/
	public String insertOne(T entity){
		Map<String, Object> param = MapUtils.getJaveBeanToMap(entity);
		param.remove("id");
		Document document = new Document(param);
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		try {
			mongoCollection.insertOne(clientSession, document);
		} catch (MongoSocketReadTimeoutException e) {
			mongoCollection.insertOne(clientSession, document);
		}
		
		ObjectId objectId =  (ObjectId) document.get("_id");
		return objectId.toString();
	}
	
	/**  
	* @Title: insertList  
	* @Description: 添加多条数据
	* @param list 数据集合 
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public void insertList(List<T> list) {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		List<Document> documents = new ArrayList<>();
		for (T entity : list) {
			Map<String, Object> param = MapUtils.getJaveBeanToMap(entity);
			MapUtils.mapClearEmpty(param);
			Document document = new Document(param);
			documents.add(document);
		}
		try {
			mongoCollection.insertMany(clientSession, documents );
		} catch (MongoSocketReadTimeoutException e) {
			mongoCollection.insertMany(clientSession, documents );
		}
		
	}
	
	/**  
	* @Title: delete  
	* @Description: 根据条件删除数据
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public void delete(Map<String, Object> param) {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		Document document = new Document(param);
		try {
			mongoCollection.deleteMany(clientSession, document);
		} catch (MongoSocketReadTimeoutException e) {
			mongoCollection.deleteMany(clientSession, document);
		}
		
	}
	
	/**  
	* @Title: deleteById  
	* @Description: 根据主键id删除数据
	* @param id 主键id
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public void deleteById(String id) {
		Map<String, Object> map = new HashMap<>();
		map.put("_id",new ObjectId(id));
		this.delete(map);
	}
	
	/**  
	*  多个id删除数据
	* @param ids id集合
	* @throws  
	*/
	public void deleteByIdList(List<String> ids) {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		List<ObjectId> idList = new ArrayList<>();
		for (String id : ids) {
			idList.add(new ObjectId(id));
		}
		Document document = new Document("$in",idList);
		Document options = new Document("_id",document);
		try {
			mongoCollection.deleteMany(clientSession, options);
		} catch (MongoSocketReadTimeoutException e) {
			mongoCollection.deleteMany(clientSession, options);
		}
		
	}
}

map工具类  MapUtils.java

package com.tree.common.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;

/**  
* @ClassName: MapUtil  
* @Description: map工具类
* @author chen shihua
* @date 2018年7月10日 下午3:46:20 
* @version V1.0  
*/
public class MapUtils {

	/**  
	* @Title: getJaveBeanToMap  
	* @Description: javabean转Map  
	* @return Map<String,Object>    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public static Map<String, Object> getJaveBeanToMap(Object obj)  {
		if (obj == null) {
	        return null;
	    }
	    Map<String, Object> map = new HashMap<String, Object>();
		try {
		
		    BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
		    PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
		    for (PropertyDescriptor property : propertyDescriptors) {
		        String key = property.getName();
		        System.out.println("key:"+key);
		        // 过滤class属性
		        if (!key.equals("class")) {
		            // 得到property对应的getter方法
		            Method getter = property.getReadMethod();
		            Object value = getter.invoke(obj);

		            map.put(key, value);
		        }

		    }
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("java对象转Map失败:"+e.getMessage());
		}
	    
	    return map;
	}
	
	public static Object mapToObject(Map<String, Object> map, Class<?> beanClass){    
		try {
			 if (map == null)  
		            return null;  
			ConvertUtils.register(new DateConverter(null), java.util.Date.class);
	        Object obj = beanClass.newInstance();  
	        BeanUtils.populate(obj, map);  
	        return obj;  
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
       
    }   
	
	/**  
	* @Title: mapClearEmpty  
	* @Description: 去除map中值为空置的键值对   
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public static void mapClearEmpty(Map<String,Object> map) {
		Iterator<String> iterator = map.keySet().iterator();
		while (iterator.hasNext()) {
			String key = iterator.next();
			Object value = map.get(key);
			if(value == null) {
				iterator.remove();
			}
		}
	}
}

注入bean的工具类 SpringUtil.java

package com.tree.common.util;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Service;


/**
* @ClassName: SpringUtils  
* @Description: 注入bean的工具类
* @author chen shihua
* @version V1.0
*    
 */
@Service("springUtil")
public final class SpringUtil implements BeanFactoryPostProcessor {

	// Spring应用上下文环境
    private static ConfigurableListableBeanFactory beanFactory;

    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtil.beanFactory = beanFactory;
    }

    
    /**
    * @Title: getBean  
    * @Description: 获取对象   
    * @return Object 一个以所给名字注册的bean的实例
    * @throws  
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException {
        return (T) beanFactory.getBean(name);
    }

    /**
     * 
    * @Title: getBean  
    * @Description: 获取类型为requiredType的对象
    * @return T    返回类型  
    * @throws   org.springframework.beans.BeansException
     */
    
    public static <T> T getBean(Class<T> clz) throws BeansException {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
    * @Title: containsBean  
    * @Description: 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true 
    * @return boolean    返回类型  
    * @throws  
     */
    public static boolean containsBean(String name) {
        return beanFactory.containsBean(name);
    }

    /**
    * @Title: isSingleton  
    * @Description: 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)  
    * @return boolean    返回类型  
    * @throws  
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.isSingleton(name);
    }

    
    /**
    * @Title: getType  
    * @Description: 注册对象的类型  
    * @return Class 注册对象的类型
    * @throws  org.springframework.beans.factory.NoSuchBeanDefinitionException
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getType(name);
    }

    /**
    * @Title: getAliases  
    * @Description: 如果给定的bean名字在bean定义中有别名,则返回这些别名   
    * @return String[]    返回类型  
    * @throws  NoSuchBeanDefinitionException
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException {
        return beanFactory.getAliases(name);
    }

}

拦截器,用去开启事务和提交事务   TransactionInterceptor.java

package com.tree.common.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.mongodb.MongoClient;
import com.tree.common.base.BaseController;
import com.tree.common.config.MongoTransactionHandle;
import com.tree.common.constant.ResultCode;
import com.tree.common.util.SendMsgUtil;
import com.tree.common.util.SpringUtil;
import com.tree.modules.info.entity.User;
import com.tree.modules.info.entity.vo.LoginUser;

/**  
* @ClassName: TransactionInterceptor  
* @Description: 事务拦截器
* @author chen shihua
* @date 2018年7月10日 下午4:14:39 
* @version V1.0  
*/
public class TransactionInterceptor extends BaseController implements HandlerInterceptor {

	/**
	 * 该方法会在控制器方法前执行,其返回值表示是否中断后续操作
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		String uri = request.getRequestURI();
		if(!uri.contains("/xueshu/login") && !uri.contains("/xueshu/register")) {
			User user = LoginUser.get(request.getSession());
			if(user == null) {//用户未登录
				resultCodeAndMsg(ResultCode.NOT_LOG_IN, "用户未登录");
				SendMsgUtil.sendJsonMessage(response, result());
				return false;
			}else {
//				String token = request.getParameter("token");
				String userId = user.getId();
//				Long loginTime = user.getLoginTime();  
				//验证token
//				String tokenMd5 = MD5Util.getMD5(userId+"---"+loginTime);
//				if(StringUtils.isBlank(token)) {
//					resultCodeAndMsg(ResultCode.ERROR, "令牌验证失败");
//					SendMsgUtil.sendJsonMessage(response, baseResult);
//					return false;
//				}else {
//					if(token.equals(tokenMd5)) {
//						setHeader(token, userId);
//					}else {
//						resultCodeAndMsg(ResultCode.ERROR, "令牌验证失败");
//						SendMsgUtil.sendJsonMessage(response, baseResult);
//						return false;
//					}
//				}
				setHeader("", userId);
				LoginUser.setUser(user);
			}
		}
		MongoClient mongoClient = SpringUtil.getBean("mongoClient");
		MongoTransactionHandle.startTransaction(mongoClient);//开启事务
		return true;
	}
	
	/**
	 * 该方法会在控制器方法调用之后,且解析视图之前执行
	 */

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		MongoTransactionHandle.commitTransaction();//提交事务
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub
		
	}

}

monogDB 事务处理器 MongoTransactionHandle.java

package com.tree.common.config;

import com.mongodb.MongoClient;
import com.mongodb.MongoException;
import com.mongodb.client.ClientSession;

/**  
* @ClassName: MongoTransactionHandle  
* @Description: monogDB 事务处理器
* @author chen shihua
* @date 2018年7月10日 下午1:46:00 
* @version V1.0  
*/
public class MongoTransactionHandle {
	
	
	private static ThreadLocal<ClientSession> clientSessionLocal = new ThreadLocal<ClientSession>();
	
	/**  
	* @Title: startTransaction  
	* @Description: 开启事务
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public static void startTransaction(MongoClient mongoClient) {
		ClientSession clientSession = mongoClient.startSession();
		while (true) {
			try {
				clientSession.startTransaction();
				break;
			} catch (Exception e) {
				clientSession.abortTransaction();
			}
		}
		MongoTransactionHandle.setClientSession(clientSession);
		System.out.println("======================开启事务=====================");
	}
	
	/**  
	* @Title: commitTransaction  
	* @Description: 提交事务
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public static void commitTransaction() {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		while (true) {
			try {
				if(clientSession != null) {
					clientSession.commitTransaction();
					System.out.println("======================提交事务=====================");
				}
				break;
			} catch (MongoException e) {
				// can retry commit
				if (e.hasErrorLabel(MongoException.UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)) {
					System.out.println("UnknownTransactionCommitResult, retrying commit operation ...");
					continue;
				} else {
					System.out.println("Exception during commit ...");
					throw e;
				}
			}
		}
	}
	
	/**  
	* @Title: abortTransaction  
	* @Description: 中止事务 
	* @return void    返回类型  
	* @author chen shihua
	* @throws  
	*/
	public static void abortTransaction() {
		ClientSession clientSession = MongoTransactionHandle.getClientSession();
		if(clientSession != null) {
			clientSession.abortTransaction();
			clientSession = null;
			MongoTransactionHandle.setClientSession(clientSession);
			System.out.println("======================中止事务=====================");
		}
//		throw new XueShuException("异常");
	}
	
	public static  ClientSession getClientSession() {
    	return clientSessionLocal.get();
	}

	public static void setClientSession(ClientSession clientSession) {
		clientSessionLocal.set(clientSession);
	}
}

通过切面捕获未处理的异常 进行中止事务 RestServiceExceptionHandler.java

package com.tree.common.aspect;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import com.tree.common.config.MongoTransactionHandle;

/**  
* @ClassName: RestServiceExceptionHandler  
* @Description: 服务异常处理
* @author chen shihua
* @version V1.0  
*/
@Aspect
public class RestServiceExceptionHandler {

    /**  
    *  定义一个切点
    * @throws  
    */
    @Pointcut("execution(* com.tree.modules.*.service..*.*(..))")
    public void serviceMethodPointcut() {
    }

    /**  
    *  获取程序中未处理的异常
    * @param a
    * @throws  
    */
    @AfterThrowing(pointcut = "serviceMethodPointcut()", throwing = "a")
    public void handleServiceMethodException(Throwable a) {
    	//监听到异常,中止事务
    	MongoTransactionHandle.abortTransaction();
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值