java 基于springboot使用ssh(spring + springmvc + hibernate)分库配置多数据源方式

今天我们来看一下当我们需要配置多数据源时,如何进行配置。我们的项目还是基于springboot以及ssh进行搭建,项目搭建结构还是使用分布式的结构来进行搭建。如果对springboot不是很了解以及对springboot如何搭建多module没有思路的同学,可以先阅读java 搭建基于springboot的ssh(spring + springmvc + hibernate)的gradle项目(基础篇)以及java 搭建基于springboot的ssh(spring + springmvc + hibernate)的gradle项目(添加多Module篇) ,因为今天的侧重点是如何添加多数据源,所以不会将过多的解释放到项目搭建上。

需求

我们将创建三个module 分别为datasource、one-service以及two-service,其中one-service以及two-service中分别对应不同的库(datasourceone库和datasourcetwo库)。最终我们将使用datasource依赖one-service以及two-service查询所需要的数据。

搭建环境

jdk:1.8
框架:springboot + spring + springmvc + hibernate
数据库 : mysql
项目管理 : gradle

最终结构图

整体结构

这里写图片描述

datasource结构

这里写图片描述

one-service结构

这里写图片描述

two-service结构

这里写图片描述

搭建过程

我们主要拿one-service进行讲解,然后只会对one-service以及two-service之间的不同进行说明。

第一步

首先因为我们采用了分布式的开发,所以我们的one-service会被打成jar包,因此springboot无法自动读取到one-service中的application.properties文件,所以我们需要添加配置让其读取到properties文件中我们所配置的数据源。

OneLoadProperties

package com.beyondli.oneservice.config;

import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

/**
 * 启动项目时自动读取配置文件
 */
//value值为properties文件名
@PropertySource(value = "application-one.properties")
@Component
public class OneLoadProperties {
}

application-one.properties

spring.datasource.one.url=jdbc:mysql://localhost:3306/datasourceone
spring.datasource.one.username=root
spring.datasource.one.password=123456
spring.datasource.one.driverClassName=com.mysql.jdbc.Driver
第二步

配置一个dataSource,具体代码解释在代码的注释中,可有助于理解。

OneDataSourceConfig

package com.beyondli.oneservice.config;

/**
 * Created by beyondLi on 2017/7/26.
 */

import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

/**
 * 配置数据源
 */

@Configuration  //声明是一个配置文件
public class OneDataSourceConfig {
    //此注解代表此数据源为主数据源,因为当多数据源时,springboot需要一个默认主数据源(当然也可以通过配置将此要求取消),并且当我们controller层依赖多service层时,必须依赖一个有主数据源注解的service,否则项目启动报错.
    @Primary
    @Bean(name = "oneDataSource")
    //此注解表示在properties文件中的key的前缀
    @ConfigurationProperties(prefix = "spring.datasource.one")
    public DataSource oneDataSource() {
        return DataSourceBuilder.create().build();
    }
}
第三步

我们需要给EntityManager进行属性设置,从而达到我们注入此对象后可拿到对应数据源的操作对象。简单地说就是配置jpa以及事务。

OneJpaConfig

package com.beyondli.oneservice.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.util.Map;

/**
 * Created by beyondLi on 2017/7/26.
 * 设置jpa对象
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "studentEntityManagerFactory",
        transactionManagerRef = "studentTransactionManager",
        basePackages = {"com.beyondli.oneservice.domain"}) //设置Repository所在位置
public class OneJpaConfig {
    //注入dataSource
    @Autowired
    @Qualifier("oneDataSource")
    private DataSource oneDataSource;
    //声明是主数据源,原理同上
    @Primary
    //因为此bean没有设置name属性,所以名称默认为方法名
    @Bean
    public LocalContainerEntityManagerFactoryBean studentEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        //packages中设置实体类所在位置,persistencuUnit中的值个人感觉只是一个标示,名称对项目并无影响.
        return builder.dataSource(oneDataSource).properties(getVendorProperties(oneDataSource)).packages("com.beyondli.oneservice.domain").persistenceUnit("onePersistenceUnit").build();
    }

    @Autowired
    private JpaProperties jpaProperties;

    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }
    //声明是主数据源,原理同上
    @Primary
    //因为此bean没有设置name属性,所以名称默认为方法名
    @Bean
    public PlatformTransactionManager studentTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(studentEntityManagerFactory(builder).getObject());
    }
}
第四步

现在我们来添加事务以及注入EntityManager
StudentServiceImpl

package com.beyondli.oneservice.application.service;

import com.beyondli.oneservice.application.responsedo.StudentInfoResponseDO;
import com.beyondli.oneservice.domain.teacher.Student;
import com.beyondli.oneservice.domain.teacher.StudentRepository;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * Created by beyondLi on 2017/7/25.
 */
@Service
public class StudentServiceImpl implements StudentService {
    @Autowired
    StudentRepository studentRepository;
    /**
     *
     * @return
     */
    @Override
    //添加事务,名称为当时配置的bean的方法名
    @Transactional(value = "studentTransactionManager")
    public StudentInfoResponseDO getStudent() {
        Student student = studentRepository.getStudent();
        //1.获取mapperFactory对象
        MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        return mapperFactory.getMapperFacade(Student.class, StudentInfoResponseDO.class).map(student);
    }
}

StudentRepositoryImpl

package com.beyondli.oneservice.infrastructure;

import com.beyondli.oneservice.domain.teacher.Student;
import com.beyondli.oneservice.domain.teacher.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import javax.persistence.EntityManager;
import java.util.List;

/**
 * Created by beyondLi on 2017/7/25.
 */
@Repository
public class StudentRepositoryImpl implements StudentRepository{
    @Autowired
    @Qualifier(value = "studentEntityManagerFactory")
    EntityManager entityManager;

    @Override
    public Student getStudent() {
        List<Student> resultList = entityManager.createQuery("FROM Student")
                .setFirstResult(0)
                .setMaxResults(1)
                .getResultList();
        if (resultList.size() == 0) {
            return null;
        }
        return resultList.get(0);
    }
}

one-service的数据源基本已完成,对于two-service的module中的数据源配置与one-service数据源配置相同。需要注意的是,在two-service的config文件中的所有配置文件需要将@Primary全部进行删除。因为springboot需要一个主数据源,但是也只能有一个主数据源。如果当出现多主数据源或没有主数据源项目将报错无法启动。

测试

最后我们启动项目检验一下是否达到了效果。

数据库
这里写图片描述
测试结果
这里写图片描述
这里写图片描述

好了 效果达成,我们分别从不同的数据库中取出了所需要的数据。
为防止在讲解过程中有疏漏,本人将代码的demo已上传到网上,如有需要自行下载。
http://download.csdn.net/download/liboyang71/9913785
链接:http://pan.baidu.com/s/1pLHkKrh 密码:sbgb

以上观点均属本人个人理解,如有错误或不足,望指出,共同成长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值