JSP 与 MyBatis 实现数据库分库分表示例
随着互联网技术的飞速发展,企业应用的数据量越来越大,传统的单库单表架构已经无法满足日益增长的数据处理需求。为了提高系统的性能和可扩展性,数据库分库分表技术应运而生。本文将结合 JSP 和 MyBatis 框架,实现一个简单的数据库分库分表示例,帮助读者了解如何在实际项目中应用这一技术。
环境准备
在开始之前,我们需要准备以下环境:
1. JDK 1.8 或更高版本
2. MySQL 5.7 或更高版本
3. Tomcat 8.5 或更高版本
4. MyBatis 3.5.2 或更高版本
5. Maven 3.6.3 或更高版本
项目结构
以下是项目的目录结构:
src/
|-- main/
| |-- java/
| | |-- com/
| | | |-- example/
| | | | |-- controller/
| | | | | |-- UserAction.java
| | | | |-- mapper/
| | | | | |-- UserMapper.java
| | | | |-- model/
| | | | | |-- User.java
| | | | |-- service/
| | | | | |-- UserService.java
| | | | |-- SpringConfig.java
| |-- resources/
| | |-- mybatis/
| | | |-- mapper/
| | | | |-- UserMapper.xml
| | |-- db.properties
| |-- web.xml
|-- test/
| |-- java/
| | |-- com/
| | | |-- example/
| | | | |-- UserMapperTest.java
|-- pom.xml
数据库设计
为了演示分库分表技术,我们假设有两个数据库,分别存储不同类型的数据:
1. `user_db`:存储普通用户数据
2. `admin_db`:存储管理员数据
以下是两个数据库的表结构:
sql
CREATE TABLE `user_db`.`user` (
`id` INT NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `admin_db`.`admin` (
`id` INT NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`password` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`)
);
MyBatis 配置
在 `resources/mybatis/mapper` 目录下创建 `UserMapper.xml` 文件,配置 MyBatis 的映射信息:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectUser" resultType="com.example.model.User">
SELECT FROM user_db.user WHERE id = {id}
</select>
<select id="selectAdmin" resultType="com.example.model.User">
SELECT FROM admin_db.admin WHERE id = {id}
</select>
</mapper>
在 `resources/db.properties` 文件中配置数据库连接信息:
properties
数据库连接信息
user_db.driver=com.mysql.cj.jdbc.Driver
user_db.url=jdbc:mysql://localhost:3306/user_db?useSSL=false&serverTimezone=UTC
user_db.username=root
user_db.password=root
admin_db.driver=com.mysql.cj.jdbc.Driver
admin_db.url=jdbc:mysql://localhost:3306/admin_db?useSSL=false&serverTimezone=UTC
admin_db.username=root
admin_db.password=root
Spring 配置
在 `src/main/java/com/example/SpringConfig.java` 文件中配置 Spring 和 MyBatis 的整合:
java
package com.example;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@PropertySource("classpath:db.properties")
@MapperScan("com.example.mapper")
public class SpringConfig {
private final Environment env;
public SpringConfig(Environment env) {
this.env = env;
}
@Bean
public DataSource dataSource() {
AbstractRoutingDataSource dataSource = new AbstractRoutingDataSource() {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDbType();
}
};
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("user_db", createDataSource(env.getProperty("user_db.driver"), env.getProperty("user_db.url"), env.getProperty("user_db.username"), env.getProperty("user_db.password")));
dataSourceMap.put("admin_db", createDataSource(env.getProperty("admin_db.driver"), env.getProperty("admin_db.url"), env.getProperty("admin_db.username"), env.getProperty("admin_db.password")));
dataSource.setTargetDataSources(dataSourceMap);
dataSource.setDefaultTargetDataSource(dataSourceMap.get("user_db"));
return dataSource;
}
private DriverManagerDataSource createDataSource(String driver, String url, String username, String password) {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
数据库路由
在 `src/main/java/com/example/mapper/UserMapper.java` 文件中,定义一个 `DataSourceContextHolder` 类,用于存储当前线程的数据库类型:
java
package com.example.mapper;
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return contextHolder.get();
}
public static void clearDbType() {
contextHolder.remove();
}
}
在 `src/main/java/com/example/service/UserService.java` 文件中,修改 `selectUser` 和 `selectAdmin` 方法,根据用户类型设置数据库类型:
java
package com.example.service;
import com.example.mapper.UserMapper;
import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User selectUser(int id) {
DataSourceContextHolder.setDbType("user_db");
return userMapper.selectUser(id);
}
public User selectAdmin(int id) {
DataSourceContextHolder.setDbType("admin_db");
return userMapper.selectAdmin(id);
}
}
JSP 页面
在 `src/main/webapp/WEB-INF/jsp` 目录下创建 `user.jsp` 和 `admin.jsp` 页面,分别用于展示用户和管理员信息:
jsp
<!-- user.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>User Information</title>
</head>
<body>
<h1>User Information</h1>
<%
UserService userService = (UserService) application.getAttribute("userService");
User user = userService.selectUser(1);
if (user != null) {
%>
<p>Username: ${user.getUsername()}</p>
<p>Password: ${user.getPassword()}</p>
<%
} else {
%>
<p>User not found.</p>
<%
}
%>
</body>
</html>
jsp
<!-- admin.jsp -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Admin Information</title>
</head>
<body>
<h1>Admin Information</h1>
<%
UserService userService = (UserService) application.getAttribute("userService");
User admin = userService.selectAdmin(1);
if (admin != null) {
%>
<p>Username: ${admin.getUsername()}</p>
<p>Password: ${admin.getPassword()}</p>
<%
} else {
%>
<p>Admin not found.</p>
<%
}
%>
</body>
</html>
总结
本文通过 JSP 和 MyBatis 框架,实现了一个简单的数据库分库分表示例。在实际项目中,我们可以根据业务需求,灵活地调整数据库路由策略,提高系统的性能和可扩展性。希望本文能对您有所帮助。
Comments NOTHING