美文网首页
spring+mybatis读写分离

spring+mybatis读写分离

作者: donglq | 来源:发表于2017-10-05 11:37 被阅读0次

    操作类型枚举

    package com.dlq.blog.db;
    
    /**
     * 读、写类型枚举
     * @author donglq
     * @date 2017/10/5 1:50
     */
    public enum DBWRType {
        WRITE(1, "WRITE", "写"), READ(2, "READ", "读");
    
        DBWRType(int code, String name, String desc) {
            this.code = code;
            this.name = name;
            this.desc = desc;
        }
    
        public int code;
    
        public String name;
    
        public String desc;
    
    }
    
    

    自定义注解

    package com.dlq.blog.db.annotation;
    
    import com.dlq.blog.db.DBWRType;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 读、写注解
     * @author donglq
     * @date 2017/10/5 1:54
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface DBWR {
    
        DBWRType value() default DBWRType.WRITE;
    
    }
    

    上下文工具

    package com.dlq.blog.db;
    
    /**
     * 工具类,存放当前线程数据源key和表名后缀
     * 使用treadLocal的方式来保证线程安全
     * @author donglq
     * @date 2017/10/3 22:56
     */
    public class DBContext {
    
        /**数据库逻辑名**/
        private static final ThreadLocal<String> dbKeyHolder = new ThreadLocal<String>();
    
        /**表明后缀**/
        private static final ThreadLocal<String> tableSuffixHolder = new ThreadLocal<String>();
    
        public static void setDbKey(String dbKey) {
            dbKeyHolder.set(dbKey);
        }
    
        public static String getDbKey() {
            return dbKeyHolder.get();
        }
    
        public static void clearDbKey() {
            dbKeyHolder.remove();
        }
    
        public static void setTableSuffix(String tableIndex){
            tableSuffixHolder.set(tableIndex);
        }
    
        public static String getTableSuffix(){
            return tableSuffixHolder.get();
        }
        public static void clearTableSuffix(){
            tableSuffixHolder.remove();
        }
    
    }
    

    AOP拦截

    package com.dlq.blog.db;
    
    import com.dlq.blog.db.annotation.DBWR;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Service;
    
    import java.lang.reflect.Method;
    
    /**
     * 读写分离路由
     * @author donglq
     * @date 2017/10/5 1:57
     */
    @Aspect
    @Service
    public class DBWRRoute {
    
        @Pointcut("@annotation(com.dlq.blog.db.annotation.DBWR)")
        public void aopPoint() {
        }
    
        @Before("aopPoint()")
        public Object doRoute(JoinPoint jp) throws Throwable {
            //根据JoinPoint jp 获取方法名称和参数
            Method method = getMethod(jp);
            //获取注解
            DBWR dbwr = method.getAnnotation(DBWR.class);
            DBContext.setDbKey(dbwr.value().name);
            return null;
        }
    
        private Method getMethod(JoinPoint jp) throws NoSuchMethodException {
            Signature sig = jp.getSignature();
            MethodSignature msig = (MethodSignature) sig;
            return jp.getTarget().getClass().getMethod(msig.getName(), msig.getParameterTypes());
        }
    
    }
    

    动态数据源

    package com.dlq.blog.db;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    import org.springframework.lang.Nullable;
    
    /**
     * 动态获取当前数据源
     * @author donglq
     * @date 2017/10/3 22:59
     */
    public class DynamicDataSource extends AbstractRoutingDataSource {
    
        /**
         * 获取当前数据源
         * @return
         */
        @Nullable
        @Override
        protected Object determineCurrentLookupKey() {
            String dbKey = DBContext.getDbKey();
            System.out.println("dbKey: " + dbKey);
            return dbKey;
        }
    }
    

    测试

    配置
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- 引入配置文件 -->
        <bean id="propertyConfigurer"
              class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="location" value="classpath:db.properties"/>
        </bean>
    
        <!--配置读、写数据源-->
        <bean id="WRITE" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${jdbc.mysql.write}"/>
            <property name="username" value="${jdbc.mysql.username}"/>
            <property name="password" value="${jdbc.mysql.password}"/>
        </bean>
    
        <bean id="READ" class="org.apache.ibatis.datasource.pooled.PooledDataSource">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${jdbc.mysql.read}"/>
            <property name="username" value="${jdbc.mysql.username}"/>
            <property name="password" value="${jdbc.mysql.password}"/>
        </bean>
    
        <!-- 动态获取数据源 -->
        <bean id="mysqlDynamicDataSource" class="com.dlq.blog.db.DynamicDataSource">
            <property name="targetDataSources">
                <!-- 标识符类型 -->
                <map>
                    <entry key="WRITE" value-ref="WRITE"/>
                    <entry key="READ" value-ref="READ"/>
                </map>
            </property>
        </bean>
    
        <!--事务-->
        <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="mysqlDynamicDataSource"></property>
        </bean>
    
        <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"></property>
            <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property>
        </bean>
    
        <!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="mysqlDynamicDataSource"/>
            <!-- 自动扫描mapping.xml文件 -->
            <property name="mapperLocations" value="classpath*:mybatis/mapper/*.xml"></property>
        </bean>
    
        <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.dlq.blog.dao"/>
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        </bean>
    
    </beans>
    
    测试方法
    DAO
    package com.dlq.blog.dao;
    
    import org.apache.ibatis.annotations.Param;
    
    /**
     * @author donglq
     * @date 2017/10/4 10:13
     */
    public interface UserDao {
    
        Object insert(@Param("user") User user);
    
        User select(@Param("user") User user);
    
    }
    
    package com.dlq.blog.dao;
    
    /**
     * @author donglq
     * @date 2017/10/4 10:15
     */
    public class User {
    
        private int id;
    
        private String firstname;
    
        private String lastname;
    
        private int gender;
    
        private String idcard;
    
        private String address;
    
        private String tableIndex;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getFirstname() {
            return firstname;
        }
    
        public void setFirstname(String firstname) {
            this.firstname = firstname;
        }
    
        public String getLastname() {
            return lastname;
        }
    
        public void setLastname(String lastname) {
            this.lastname = lastname;
        }
    
        public int getGender() {
            return gender;
        }
    
        public void setGender(int gender) {
            this.gender = gender;
        }
    
        public String getIdcard() {
            return idcard;
        }
    
        public void setIdcard(String idcard) {
            this.idcard = idcard;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getTableIndex() {
            return tableIndex;
        }
    
        public void setTableIndex(String tableIndex) {
            this.tableIndex = tableIndex;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", firstname='" + firstname + '\'' +
                    ", lastname='" + lastname + '\'' +
                    ", gender=" + gender +
                    ", idcard='" + idcard + '\'' +
                    ", address='" + address + '\'' +
                    ", tableIndex='" + tableIndex + '\'' +
                    '}';
        }
    }
    
    
    调用
    @Resource
    UserDao userDao;
    
    @DBWR(DBWRType.WRITE)
    public Object write(User user) {
        return userDao.insert(user);
    }
    
    @DBWR(DBWRType.READ)
    public User read(User user) {
        return userDao.select(user);
    }
    

    相关文章

      网友评论

          本文标题:spring+mybatis读写分离

          本文链接:https://www.haomeiwen.com/subject/rrwhyxtx.html