欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-17 19:52:10
...

今天我们来看一下当我们需要配置多数据源时,如何进行配置。我们的项目还是基于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

最终结构图

整体结构

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

datasource结构

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

one-service结构

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

two-service结构

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

搭建过程

我们主要拿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需要一个主数据源,但是也只能有一个主数据源。如果当出现多主数据源或没有主数据源项目将报错无法启动。

测试

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

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

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

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