Database Setup
This example demonstrates a read-write database separation setup. The write database (mybatis1) handles write operations, while the read database (mybatis) handles read operations. Both databases share identical table structures.
Write Database Schema
CREATE DATABASE `mybatis1` DEFAULT CHARACTER SET utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Read Database Schema
CREATE DATABASE `mybatis` DEFAULT CHARACTER SET utf8;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Dependencies Configuration
Include the following dependencies in your Maven configuration:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
</dependencies>
Data Access Layer Configuration
Read Data Mapper
package com.example.read.mapper;
import com.example.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface ReadUserMapper {
@Select("SELECT * FROM user")
List<User> findAll();
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(int id);
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
void save(User user);
@Update("UPDATE user SET name=#{name}, age=#{age} WHERE id =#{id}")
void modify(User user);
@Delete("DELETE FROM user WHERE id =#{id}")
void remove(int id);
}
Write Data Mapper
package com.example.write.mapper;
import com.example.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface WriteUserMapper {
@Select("SELECT * FROM user")
List<User> findAll();
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(int id);
@Insert("INSERT INTO user(name, age) VALUES(#{name}, #{age})")
void save(User user);
@Update("UPDATE user SET name=#{name}, age=#{age} WHERE id =#{id}")
void modify(User user);
@Delete("DELETE FROM user WHERE id =#{id}")
void remove(int id);
}
Data Source Configuration Classes
Write Data Source Configuration
package com.example.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.example.write.mapper",
sqlSessionTemplateRef = "writeSqlSessionTemplate")
public class WriteDataSourceConfig {
@Bean(name = "writeDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.write")
@Qualifier("writeDataSource")
@Primary
public DataSource writeDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "writeSqlSessionFactory")
@Primary
public SqlSessionFactory writeSqlSessionFactory(
@Qualifier("writeDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
@Bean(name = "writeTransactionManager")
@Primary
public DataSourceTransactionManager writeTransactionManager(
@Qualifier("writeDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "writeSqlSessionTemplate")
@Primary
public SqlSessionTemplate writeSqlSessionTemplate(
@Qualifier("writeSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
Read Data Source Configuration
package com.example.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
@Configuration
@MapperScan(basePackages = "com.example.read.mapper",
sqlSessionTemplateRef = "readSqlSessionTemplate")
public class ReadDataSourceConfig {
@Bean(name = "readDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.read")
@Qualifier("readDataSource")
public DataSource readDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "readSqlSessionFactory")
public SqlSessionFactory readSqlSessionFactory(
@Qualifier("readDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
return factoryBean.getObject();
}
@Bean(name = "readTransactionManager")
public DataSourceTransactionManager readTransactionManager(
@Qualifier("readDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "readSqlSessionTemplate")
public SqlSessionTemplate readSqlSessionTemplate(
@Qualifier("readSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
Application Properties Configuration
# Read Data Source Configuration
spring.datasource.druid.read.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.druid.read.username=root
spring.datasource.druid.read.password=123456
spring.datasource.druid.read.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.read.type=com.alibaba.druid.pool.DruidDataSource
# Write Data Source Configuration
spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/mybatis1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.druid.write.username=root
spring.datasource.druid.write.password=123456
spring.datasource.druid.write.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.write.type=com.alibaba.druid.pool.DruidDataSource
# MyBatis Configuration
mybatis.type-aliases-package=com.example.model
Controller Implementation
package com.example.controller;
import com.example.model.User;
import com.example.read.mapper.ReadUserMapper;
import com.example.write.mapper.WriteUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private WriteUserMapper writeMapper;
@Autowired
private ReadUserMapper readMapper;
@GetMapping
public String getAllUsers(Model model) {
List<User> users = readMapper.findAll();
model.addAttribute("users", users);
return "user-list";
}
@PostMapping
public String createUser(Model model) {
User newUser = new User();
newUser.setName("testuser");
newUser.setAge(25);
writeMapper.save(newUser);
List<User> users = writeMapper.findAll();
model.addAttribute("users", users);
return "user-list";
}
}
Application Configuration
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = {"com.example.config", "com.example.controller"})
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Testing the Configuration
To verify the setup:
- Acess http://localhost:8080/users to retrieve data from the read database
- Submit a POST request to create new records in the write database
- Verify that read operations use the read database and write operations use the write database
- Check Druid monitoring interface for both data source connections