spring+mybatis多數據源(數據庫主從)實例

項目中用的的,展示給大家,結構如下


applicationContext.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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		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-3.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		">

	<description>Spring公共配置 </description>

	<!-- 使用annotation 自動註冊bean, 並保證@Required、@Autowired的屬性被注入 -->
	<context:component-scan base-package="com.test">
	</context:component-scan>

	<aop:aspectj-autoproxy proxy-target-class="true" />
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>classpath:app.properties</value>
		</property>
	</bean>
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dynamicDataSource" />
	</bean>
	<!-- 使用annotation定義事務 -->
	<tx:annotation-driven transaction-manager="transactionManager"
		proxy-target-class="true" />

	<!-- MyBatis配置 自動掃描entity目錄, 省掉Configuration.xml裏的手工配置 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="typeAliasesPackage" value="com.test.model" />
		<property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml" />
		<property name="dataSource">
			<ref bean="dynamicDataSource" />
		</property>
	</bean>




	<!-- 掃描basePackage下所有以@MyBatisRepository標識的 接口 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.test.dao.mybatis" />
		<!-- <property name="annotationClass" value="jarlun.framework.core.base.mybatis.MyBatisRepository" 
			/> -->
	</bean>

	<bean id="dynamicDataSource" class="com.test.holder.DynamicDataSource">
		<!-- 通過key-value的形式來關聯數據源 -->
		<property name="targetDataSources">
			<map key-type ="java.lang.String">
				<entry value-ref="master" key="master"></entry>
				<entry value-ref="slave" key="slave"></entry>
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="master" />
	</bean>






	<!-- JSR303 Validator定義 -->
	<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 會 自動註冊 -->


	<!-- 建立視圖內攔截器來解決JPA中訪問延遲加載屬性時產生的無會話異常 LazyInitializationException: could 
		not initialize proxy no session -->
	<!-- 此攔截器會注入到servlet配置中的DefaultAnnotationHandlerMapping中 -->

	<bean id="master" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<!-- Connection Info -->
		<property name="driverClassName" value="${master.jdbc.driver}" />
		<property name="url" value="${master.jdbc.url}" />
		<property name="username" value="${master.jdbc.username}" />
		<property name="password" value="${master.jdbc.password}" />

		<!-- Connection Pooling Info -->
		<property name="maxActive" value="${master.jdbc.pool.maxActive}" />
		<property name="maxIdle" value="${master.jdbc.pool.maxIdle}" />
		<property name="initialSize" value="${master.jdbc.pool.initialSize}" />
		<property name="defaultAutoCommit" value="false" />

		<!-- 連接Idle一個小時後超時 -->
		<property name="timeBetweenEvictionRunsMillis" value="3600000" />
		<property name="minEvictableIdleTimeMillis" value="3600000" />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="true" />
		<property name="testOnReturn" value="false" />
		<property name="validationQuery" value="SELECT 1" />
		<property name="logAbandoned" value="false" />
		<property name="removeAbandoned" value="true" />
		<property name="removeAbandonedTimeout" value="60" />
	</bean>


	<bean id="slave" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<!-- Connection Info -->
		<property name="driverClassName" value="${slave.jdbc.driver}" />
		<property name="url" value="${slave.jdbc.url}" />
		<property name="username" value="${slave.jdbc.username}" />
		<property name="password" value="${slave.jdbc.password}" />

		<!-- Connection Pooling Info -->
		<property name="maxActive" value="${slave.jdbc.pool.maxActive}" />
		<property name="maxIdle" value="${slave.jdbc.pool.maxIdle}" />
		<property name="initialSize" value="${slave.jdbc.pool.initialSize}" />
		<property name="defaultAutoCommit" value="false" />

		<!-- 連接Idle一個小時後超時 -->
		<property name="timeBetweenEvictionRunsMillis" value="3600000" />
		<property name="minEvictableIdleTimeMillis" value="3600000" />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="true" />
		<property name="testOnReturn" value="false" />
		<property name="validationQuery" value="SELECT 1" />
		<property name="logAbandoned" value="false" />
		<property name="removeAbandoned" value="true" />
		<property name="removeAbandonedTimeout" value="60" />
	</bean>






</beans>

app.properties

master.jdbc.driver=com.mysql.jdbc.Driver
master.jdbc.url=jdbc:mysql://120.25.155.55:3306/test
master.jdbc.username=test
master.jdbc.password=!QAZxsw2
master.jdbc.pool.maxActive=60
master.jdbc.pool.maxIdle=20
master.jdbc.pool.initialSize=10

slave.jdbc.driver=com.mysql.jdbc.Driver
slave.jdbc.url=jdbc:mysql://localhost:3306/test?useUnicode=true
slave.jdbc.username=root
slave.jdbc.password=
slave.jdbc.pool.maxActive=60
slave.jdbc.pool.maxIdle=20
slave.jdbc.pool.initialSize=10

DynamicDataSource.java

package com.test.holder;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource{  
  
    @Override  
    protected Object determineCurrentLookupKey() {  
        return DBContextHolder.getDBType();  
    }  
}  

DBContextHolder.java

package com.test.holder;

public class DBContextHolder {

      
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
      
    public static void setDBType(String dbType) {  
        contextHolder.set(dbType);  
    }  
      
    public static String getDBType() {  
        return contextHolder.get();  
    }  
      
    public static void clearDBType() {  
        contextHolder.remove();  
}
}

DataSource.java

package com.test.holder;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSource {
	

	Source value() default Source.master;

}

Source.java

package com.test.holder;

public enum Source {

	/* 主庫 */master, /* 從庫 */slave

}
UserMapper.java

package com.test.dao.mybatis;

import org.apache.ibatis.annotations.Param;

import com.test.model.UserModel;

public interface UserMapper {
	
	UserModel findByUserId(@Param("userId")Long userId);

}

UserModel.java

package com.test.model;

public class UserModel {
	
	private long id;
	
	private String nickname;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getNickname() {
		return nickname;
	}

	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	
	
	

}

UserMapper.xml

<?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.test.dao.mybatis.UserMapper">
	
	<resultMap  id="userModel"  type="com.test.model.UserModel" >
			<result property="id" column="id" />
			<result property="nickname" column="nickname" />
	    </resultMap>
	    
		<select id="findByUserId"  resultMap="userModel" > 
		select id , nickname from db_user where id=#{userId}
		</select>
</mapper>  


UserService.java

package com.test.service;

import com.test.model.UserModel;

public interface UserService {
	

	 UserModel findByMasterUserId(long userId);
	
	
	 UserModel findBySlaveUserId(long userId);

}

UserServiceImpl.java

package com.test.service.impl;

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

import com.test.dao.mybatis.UserMapper;
import com.test.holder.DataSource;
import com.test.holder.Source;
import com.test.model.UserModel;
import com.test.service.UserService;

@Service("userServiceImpl")
public class UserServiceImpl implements UserService{
	
	@Autowired
	private UserMapper userMapper;
	@Transactional(rollbackFor={Exception.class})
	@DataSource(value=Source.master)
	public UserModel findByMasterUserId(long userId){
		return this.userMapper.findByUserId(userId);
	}
	
	
	@Transactional(rollbackFor={Exception.class})
	@DataSource(value=Source.slave)
	public UserModel findBySlaveUserId(long userId){
		return this.userMapper.findByUserId(userId);
	}

}

aop攔截

DataSourceContextAop.java

package com.test.aop;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import com.test.holder.DBContextHolder;
import com.test.holder.DataSource;

@Aspect
@Order(value=1)
@Component
public class DataSourceContextAop {

	@Around("execution(@com.test.holder.DataSource * com.test.service.impl.*.*(..))")
	public Object setDynamicDataSource(ProceedingJoinPoint pjp) throws Throwable {
		Method method = this.getMethod(pjp);
		DataSource dataSource = method.getAnnotation(DataSource.class);
		if (dataSource != null) {
			DBContextHolder.setDBType(dataSource.value().name());
		}
			return pjp.proceed();
	}

	
	public Method getMethod(JoinPoint pjp) {
		Method method = null;
		MethodSignature signature = (MethodSignature) pjp.getSignature();
		method = signature.getMethod();
		return method;
	}

}

最後測試

Test.java

package test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.service.UserService;

public class Test {

	
	public static void main(String[] args) {
		 ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
	     UserService userService = (UserService) ac.getBean("userServiceImpl");  
	     System.out.println(userService.findByMasterUserId(1000001).getNickname());  
	     System.out.println(userService.findBySlaveUserId(1000001).getNickname());  

	}
	
	
}

謝謝

而外加個hibernate和mybatis混用的配置

<?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:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
		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-3.0.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		">

	<description>Spring公共配置 </description>

	<!-- 使用annotation 自動註冊bean, 並保證@Required、@Autowired的屬性被注入 -->
	<context:component-scan base-package="com.test">
	</context:component-scan>

	<aop:aspectj-autoproxy proxy-target-class="true" />
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>classpath:app.properties</value>
		</property>
	</bean>
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dynamicDataSource" />
	</bean>
	
		<!-- Jpa Entity Manager 配置 -->
	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dynamicDataSource" />
		<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter" />
		<property name="packagesToScan" value="com.test.entity" />
		<property name="jpaProperties">
			<props>
				<!-- <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
				</prop>
				<prop key="net.sf.ehcache.configurationResourceName">ehcache/ehcache-hibernate.xml</prop> -->
				<!-- 命名規則 My_NAME->MyName -->
				<prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
				<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
			</props>
		</property>
	</bean>
	<bean id="hibernateJpaVendorAdapter"
		class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
		<property name="databasePlatform">
			<bean factory-method="getDialect"
				class="org.springside.modules.persistence.Hibernates">
				<constructor-arg ref="dynamicDataSource" />
			</bean>
		</property>
	</bean>
	<!-- 使用annotation定義事務 -->
	<tx:annotation-driven transaction-manager="transactionManager"
		proxy-target-class="true" />

	<!-- MyBatis配置 自動掃描entity目錄, 省掉Configuration.xml裏的手工配置 -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="typeAliasesPackage" value="com.test.model" />
		<property name="mapperLocations" value="classpath*:/mybatis/*Mapper.xml" />
		<property name="dataSource">
			<ref bean="dynamicDataSource" />
		</property>
	</bean>




	<!-- 掃描basePackage下所有以@MyBatisRepository標識的 接口 -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.test.dao.mybatis" />
		<!-- <property name="annotationClass" value="jarlun.framework.core.base.mybatis.MyBatisRepository" 
			/> -->
	</bean>

	<bean id="dynamicDataSource" class="com.test.holder.DynamicDataSource">
		<!-- 通過key-value的形式來關聯數據源 -->
		<property name="targetDataSources">
			<map key-type ="java.lang.String">
				<entry value-ref="master" key="master"></entry>
				<entry value-ref="slave" key="slave"></entry>
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="master" />
	</bean>






	<!-- JSR303 Validator定義 -->
	<!-- 以下 validator ConversionService 在使用 mvc:annotation-driven 會 自動註冊 -->


	<!-- 建立視圖內攔截器來解決JPA中訪問延遲加載屬性時產生的無會話異常 LazyInitializationException: could 
		not initialize proxy no session -->
	<!-- 此攔截器會注入到servlet配置中的DefaultAnnotationHandlerMapping中 -->

	<bean id="master" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<!-- Connection Info -->
		<property name="driverClassName" value="${master.jdbc.driver}" />
		<property name="url" value="${master.jdbc.url}" />
		<property name="username" value="${master.jdbc.username}" />
		<property name="password" value="${master.jdbc.password}" />

		<!-- Connection Pooling Info -->
		<property name="maxActive" value="${master.jdbc.pool.maxActive}" />
		<property name="maxIdle" value="${master.jdbc.pool.maxIdle}" />
		<property name="initialSize" value="${master.jdbc.pool.initialSize}" />
		<property name="defaultAutoCommit" value="false" />

		<!-- 連接Idle一個小時後超時 -->
		<property name="timeBetweenEvictionRunsMillis" value="3600000" />
		<property name="minEvictableIdleTimeMillis" value="3600000" />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="true" />
		<property name="testOnReturn" value="false" />
		<property name="validationQuery" value="SELECT 1" />
		<property name="logAbandoned" value="false" />
		<property name="removeAbandoned" value="true" />
		<property name="removeAbandonedTimeout" value="60" />
	</bean>


	<bean id="slave" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<!-- Connection Info -->
		<property name="driverClassName" value="${slave.jdbc.driver}" />
		<property name="url" value="${slave.jdbc.url}" />
		<property name="username" value="${slave.jdbc.username}" />
		<property name="password" value="${slave.jdbc.password}" />

		<!-- Connection Pooling Info -->
		<property name="maxActive" value="${slave.jdbc.pool.maxActive}" />
		<property name="maxIdle" value="${slave.jdbc.pool.maxIdle}" />
		<property name="initialSize" value="${slave.jdbc.pool.initialSize}" />
		<property name="defaultAutoCommit" value="false" />

		<!-- 連接Idle一個小時後超時 -->
		<property name="timeBetweenEvictionRunsMillis" value="3600000" />
		<property name="minEvictableIdleTimeMillis" value="3600000" />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="true" />
		<property name="testOnReturn" value="false" />
		<property name="validationQuery" value="SELECT 1" />
		<property name="logAbandoned" value="false" />
		<property name="removeAbandoned" value="true" />
		<property name="removeAbandonedTimeout" value="60" />
	</bean>






</beans>


發佈了113 篇原創文章 · 獲贊 69 · 訪問量 45萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章