Three, SpringBoot mybatis integration of multiple data sources and sub-library sub-table

Foreword

To be honest, this chapter did not intend to speak, because the configuration of multiple data sources There are many similar online tutorials. But recently, because the project points to use library sub-table, so let me look to see how to achieve. I think on a blog spoke to configure multiple environments, different circumstances call to the database, then the next will be used in an environment more libraries will talk about it. So only this article.
We first look at the project structure the project today, be based on a blog post on some additions and changes, mainly to increase a config file, dao carved in two sub-packages mapper1 and mapper2 will move to the previous UserMapper mapper1 in. Well, to start text
file

Multiple Data Source Configuration

background

Prior to this, we would first talk about why there are multiple data sources. If the project is small, of course, is that all data processing and logic operations are the same library. But when a large amount of business, it would take into account the sub-libraries. Than I will also log storage data stored in a separate database. Or user rights information in a single place inventory. If this is simply a sub-library, a project on the use of 2 to 4 database, this multi data source configuration makes sense it. These data source configured in the configuration file, has a unique identity. Project loaded at boot time are initialized, and then when called, which would like to use the library on which data source connection instance just fine.

If you do not integrate mybatis then directly use spring comes jdbcTemplate, then configure multiple data sources, and the use of relatively simple, but the integration mybatis, then it is relatively more complex. We will explain step by step.

Modify the configuration file

Open the application-dev.yml file, add a data source.

#开发环境
spring:
  # 数据源配置
  datasource:
    one:
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://192.168.252.53:3306/zlflovemm?characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=CONVERT_TO_NULL
      username: root
      password: 123456
      max-idle: 10
      max-wait: 10000
      min-idle: 5
      initial-size: 5
    two:
      driver-class-name: com.mysql.jdbc.Driver
      jdbc-url: jdbc:mysql://192.168.252.53:3306/zlfdb?characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=CONVERT_TO_NULL
      username: root
      password: 123456
      max-idle: 10
      max-wait: 10000
      min-idle: 5
      initial-size: 5

It should be noted that if you are using springboot 2.0 above, then note the driver-class-name and
jdbc-url rather than driverClassName and url. Here is a pit, to remind you about.

Configuration data source

Next, we need to manually load what data sources, we create DataSourcesConfig class in the config

@Configuration
public class DataSourcesConfig {

    @Bean(name="dbOne")
    @ConfigurationProperties(prefix = "spring.datasource.one")
    @Primary
    DataSource dbOne(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name="dbTwo")
    @ConfigurationProperties(prefix = "spring.datasource.two")
    DataSource dbTwo(){
        return DataSourceBuilder.create().build();
    }

}

This defines two DataSource data sources. Are we configured in the configuration file one and two. Notes @Primary indicate default data source.

MyBatisConfigOne 类

@Configuration
@MapperScan(basePackages = "com.quellan.zlflovemm.dao.mapper1",sqlSessionFactoryRef = "sqlSessionFactory1",sqlSessionTemplateRef = "sqlSessionTemplate1")
public class MyBatisConfigOne {
    @Resource(name = "dbOne")
    DataSource dbOne;

    @Bean
    @Primary
    SqlSessionFactory sqlSessionFactory1()throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dbOne);
        return bean.getObject();
    }
    @Bean
    @Primary
    SqlSessionTemplate sqlSessionTemplate1() throws Exception{
        return new SqlSessionTemplate(sqlSessionFactory1());
    }
}

MyBatisConfigTwo 类

@Configuration
@MapperScan(basePackages = "com.quellan.zlflovemm.dao.mapper2",sqlSessionFactoryRef = "sqlSessionFactory2",sqlSessionTemplateRef = "sqlSessionTemplate2")
public class MyBatisConfigTwo {
    @Resource(name = "dbTwo")
    DataSource dbTwo;

    @Bean
    SqlSessionFactory sqlSessionFactory2()throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dbTwo);
        return bean.getObject();
    }
    @Bean
    SqlSessionTemplate sqlSessionTemplate2()throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory2());
    }
}

Note that even the difference between a file:
file

dao layer

In dao layer and create two packages mapper1 mapper2. UserMapper content type package which is exactly the same, only in a different package to distinguish which data source. And yesterday is the same.

public interface UserMapper {

    @Select("select id,username as userName,password,email,role_code as roleCode,gmt_create as gmtCreate,gmt_update as gmtUpdate,nickname as nickName,user_create as userCreate from sys_user")
    List<UserEntry> findUserList();


    @Insert({"insert into sys_user(username,password,email) values('${user.userName}','${user.password}','${user.email}')"})
    int add(@Param("user") UserEntry user);

    @Delete("delete from sys_user where id = #{id}")
    int delete(int id);
}

service layer

UserService Interface

public interface UserService {

    List<UserEntry> findUserList();

    int addUser(String userName,String password,String email);

    int deleteUser(int id);

    List<UserEntry> findUserList2();

    int addUser2(String userName,String password,String email);

    int deleteUser2(int id);
}

UserServiceImpl categories:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    protected UserMapper userMapper;

    @Autowired
    protected UserMapper2 userMapper2;


    @Override
    public List<UserEntry> findUserList() {
        return userMapper.findUserList();
    }

    @Override
    public int addUser(String userName, String password, String email) {
        UserEntry user=new UserEntry();
        user.setUserName(userName);
        user.setPassword(password);
        user.setEmail(email);
        return userMapper.add(user);
    }

    @Override
    public int deleteUser(int id) {
        return userMapper.delete(id);
    }

    @Override
    public List<UserEntry> findUserList2() {
        return userMapper2.findUserList();
    }

    @Override
    public int addUser2(String userName, String password, String email) {
        UserEntry user=new UserEntry();
        user.setUserName(userName);
        user.setPassword(password);
        user.setEmail(email);
        return userMapper2.add(user);
    }

    @Override
    public int deleteUser2(int id) {
        return userMapper2.delete(id);
    }
}

controller layer

userController

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public List<UserEntry> findUserList(){
        return userService.findUserList();
    }

    @RequestMapping(value = "/add",method = RequestMethod.GET)
    public String addUser(@RequestParam(value = "userName")String uaserName,@RequestParam(value = "password")String password,@RequestParam(value = "email")String email){
        int falg=userService.addUser(uaserName,password,email);
        if(falg>0){
            return "success";
        }
        return "error";
    }
        
    @RequestMapping(value = "/delete",method = RequestMethod.GET)
    public String deleteUser(@RequestParam(value = "id")int id){
        if(userService.deleteUser(id)>0){
            return "success";
        }
        return "error";
    }

    @RequestMapping(value = "/list2",method = RequestMethod.GET)
    public List<UserEntry> findUserList2(){
        return userService.findUserList2();
    }

    @RequestMapping(value = "/add2",method = RequestMethod.GET)
    public String addUser2(@RequestParam(value = "userName")String uaserName,@RequestParam(value = "password")String password,@RequestParam(value = "email")String email){
        int falg= userService.addUser2(uaserName,password,email);
        if(falg>0){
            return "success";
        }
        return "error";
    }

    @RequestMapping(value = "/delete2",method = RequestMethod.GET)
    public String deleteUser2(@RequestParam(value = "id")int id){
        if(userService.deleteUser2(id)>0){
            return "success";
        }
        return "error";
    }
}

test

file
file
You can see it is out of tune from different libraries. This shows that our springboot configure multiple data source integration mybatis have succeeded. The most important thing is the three class configuration under config package. Everything else is common business logic, so back I did not say how the code will be synchronized to github, you want to practice, you can get the source code down to practice.

We integrate this springboot mybatis multi data source has been configured, but we can see the configuration down, if we want to configure several data sources have created the number of sub-package is used to distinguish the dao layer. If the amount of data that we are large enough to be sub-library sub-table instead of several libraries do?

Sub-library sub-table

background

In fact, the sub-library sub-table and multi-data source is the same, just more data sources, and more connected to configure all looked very bloated in the configuration, so it had to find another method. Sub-library sub-table is to configure the project in connection main library, reading library to connect the various points from the main library and dynamic loading, that interface would like to call the library to load the connection points of the sub-libraries.
I now do the project because they are not directly integrated mybatis jdbcTemplate, which can be realized not too much trouble.

Thinking

Mainly on two classes;
GetDynamicJdbcTemplate categories: manually create connections.

/**
 * @ClassName GetDynamicJdbcTemplate
 * @Description 获取动态的jdbcTemplate
 * @Author zhulinfeng
 * @Date 2019/9/20 14:35
 * @Version 1.0
 */
public class GetDynamicJdbcTemplate {

    private  String driverClassName;
    private  String url;
    private  String dbUsername;
    private  String dbPassword;
    private JdbcTemplate jdbcTemplate;

    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public GetDynamicJdbcTemplate(String driverClassName, String url, String dbUsername, String dbPassword){
        this.driverClassName=driverClassName;
        this.url=url;
        this.dbUsername=dbUsername;
        this.dbPassword=dbPassword;
        this.jdbcTemplate=new JdbcTemplate(getDataSource());
    }

    public DriverManagerDataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(dbUsername);
        dataSource.setPassword(dbPassword);
        return dataSource;
    }
}

GetJdbcTemplateMap class when the project started, reads the main library configuration, all connection points are created into the library map. We are in accordance with the Fen table, front-end interface to pass over the city you can know which database to use when the call is connected.


@Component
@Slf4j
    public class GetJdbcTemplateMap implements ApplicationRunner {

    @Autowired
    @Qualifier("baseTemplate")
    private JdbcTemplate jdbcTemplate;

    public static Map<String,JdbcTemplate> JdbcTemplateMap=new HashMap<>();

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String sql="CALL proc_baseinfo_cfg_dbsetting_query()";
        List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
        if(list!=null && !list.isEmpty()){
            insertMap(list);
        }
    }

    private void insertMap(List<Map<String, Object>> list){
        for(Map<String, Object> map :list){
            String url="jdbc:mysql://"+map.get("serverip")+":"+map.get("dbport")+"/"+map.get("dbname")+"?allowMultiQueries=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull";
            log.info(url);
            String  dbUsername=  map.get("user").toString();
            String  dbPassword=  map.get("password").toString();
            GetDynamicJdbcTemplate getDynamicJdbcTemplate=new GetDynamicJdbcTemplate(ConstantClass.DRIVERCLASSNAME,url,dbUsername,dbPassword);
            JdbcTemplate jdbcTemplate=getDynamicJdbcTemplate.getJdbcTemplate();
            JdbcTemplateMap.put(map.get("cityid").toString(),jdbcTemplate);
        }
    }
}

file

Call interface is also very convenient.
file

But speaking above only for our own unique business and also not integrated mybatis, so I did not write my own projects, provided it is here to give you an idea.

Extra

This can be considered finished, I feel writing is not very good, but do not know how to modify, being on first so be it, and then follow the ideas have to be modified. Why do not you ask me to integrate Thymeleaf page to come up. The reason why no get, because I want to do post-separation of the front and rear ends are called to form interface. So I would like first of all to build a good part of the back-end, front-end integration again.
Well, so much for you, today's code is also synchronized to the project on github friends.
github address: https: //github.com/QuellanAn/zlflovemm

Come follow ♡

Welcome to the personal public concern number "Programmers love yogurt"

Share a variety of learning materials including java, linux, big data. Information includes video documentation and source code, while sharing themselves and delivery of high-quality technology blog.

If you like attention and remember to share yo ❤
file

Guess you like

Origin www.cnblogs.com/quellanan/p/11564099.html