提交 d03f92b1 编写于 作者: L Linnea Lin

feat(database): 添加 StarRocks 数据源及用户管理功能

- 配置 StarRocks 数据源,支持双数据源切换- 创建 StarRocks 用户表及初始化脚本
- 实现 StarRocks 用户增删改查接口
- 添加 MySQL 和 StarRocks 双数据源配置类
- 更新 application.yml 支持多数据源配置- 添加 StarRocks 相关 Mapper 和 Service 实现- 提供 RESTful API 接口用于操作 StarRocks 用户数据
- 添加数据库初始化脚本和配置文件
上级 66404f3c
# StarRocks + MySQL 双数据源集成指南
本项目集成了StarRocks和MySQL双数据源,支持OLTP和OLAP场景的数据处理需求。
## 🚀 快速开始
### 1. 环境要求
- Docker & Docker Compose
- Java 8+
- Maven 3.6+
### 2. 启动环境
```bash
# 启动所有服务(MySQL + StarRocks + Redis)
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f starrocks-fe
docker-compose logs -f starrocks-be
```
### 3. 服务端口
| 服务 | 端口 | 用途 |
|------|------|------|
| MySQL | 3306 | MySQL数据库 |
| StarRocks FE | 8030 | Web管理界面 |
| StarRocks FE | 9030 | MySQL协议端口 |
| StarRocks BE | 8040 | BE Web界面 |
| Redis | 6379 | 缓存服务 |
### 4. 初始化数据
#### MySQL初始化
MySQL会自动执行 `docker/mysql/init/01-init.sql` 脚本进行初始化。
#### StarRocks初始化
```bash
# 连接到StarRocks
mysql -h127.0.0.1 -P9030 -uroot
# 执行初始化脚本
source docker/starrocks/init-starrocks.sql
```
或者直接执行:
```bash
mysql -h127.0.0.1 -P9030 -uroot < docker/starrocks/init-starrocks.sql
```
## 📊 数据源配置
### application.yml配置
```yaml
spring:
datasource:
# MySQL数据源配置
mysql:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: MySQLHikariCP
minimum-idle: 5
maximum-pool-size: 20
# StarRocks数据源配置
starrocks:
username: root
password:
url: jdbc:mysql://127.0.0.1:9030/demo?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: StarRocksHikariCP
minimum-idle: 3
maximum-pool-size: 15
```
### 数据源Bean配置
项目使用 `DataSourceConfig.java` 配置双数据源:
- **MySQL**: 主数据源,用于OLTP操作
- **StarRocks**: 分析数据源,用于OLAP操作
## 🔧 API接口
### StarRocks用户管理接口
基础URL: `/api/starrocks/user`
#### 查询接口
```bash
# 查询所有用户
GET /api/starrocks/user/list
# 根据ID查询用户
GET /api/starrocks/user/{id}
# 根据用户ID查询用户
GET /api/starrocks/user/userId/{userId}
# 查询用户总数
GET /api/starrocks/user/count
```
#### 创建接口
```bash
# 创建单个用户
POST /api/starrocks/user
Content-Type: application/json
{
"id": 11,
"userId": "10011",
"userNickname": "新用户",
"userHead": "https://example.com/avatar.png",
"userPassword": "password123"
}
# 批量创建用户
POST /api/starrocks/user/batch
Content-Type: application/json
[
{
"id": 12,
"userId": "10012",
"userNickname": "用户1",
"userHead": "https://example.com/avatar1.png"
},
{
"id": 13,
"userId": "10013",
"userNickname": "用户2",
"userHead": "https://example.com/avatar2.png"
}
]
```
#### 更新接口
```bash
# 更新用户信息
PUT /api/starrocks/user
Content-Type: application/json
{
"id": 11,
"userId": "10011",
"userNickname": "更新后的用户名",
"userHead": "https://example.com/new-avatar.png"
}
```
#### 删除接口
```bash
# 根据ID删除用户
DELETE /api/starrocks/user/{id}
# 根据用户ID删除用户
DELETE /api/starrocks/user/userId/{userId}
```
## 🏗️ 项目结构
```
src/main/java/cn/bugstack/xfg/frame/
├── config/
│ └── DataSourceConfig.java # 双数据源配置
├── dao/
│ ├── IUserDao.java # MySQL用户DAO
│ └── starrocks/
│ └── IStarRocksUserDao.java # StarRocks用户DAO
├── service/
│ ├── IUserService.java # MySQL用户服务
│ ├── IStarRocksUserService.java # StarRocks用户服务
│ └── impl/
│ └── StarRocksUserServiceImpl.java # StarRocks用户服务实现
└── controller/
├── UserController.java # MySQL用户控制器
└── StarRocksUserController.java # StarRocks用户控制器
src/main/resources/mybatis/mapper/
├── User_Mapper.xml # MySQL用户映射
└── StarRocks_User_Mapper.xml # StarRocks用户映射
```
## 🔍 使用场景
### MySQL (OLTP)
- 用户注册、登录
- 实时数据更新
- 事务性操作
- 高并发读写
### StarRocks (OLAP)
- 用户行为分析
- 数据统计报表
- 复杂查询分析
- 大数据量处理
## 📈 性能优化建议
### StarRocks优化
1. **分区策略**: 根据时间或业务维度进行分区
2. **索引优化**: 合理使用前缀索引和布隆过滤器
3. **数据压缩**: 启用列式存储压缩
4. **批量导入**: 使用Stream Load进行大批量数据导入
### 连接池配置
- MySQL: 适中的连接池大小,支持高并发
- StarRocks: 较小的连接池,专注于分析查询
## 🛠️ 故障排除
### 常见问题
1. **StarRocks连接失败**
```bash
# 检查StarRocks服务状态
docker-compose logs starrocks-fe
docker-compose logs starrocks-be
# 检查端口是否开放
netstat -tlnp | grep 9030
```
2. **数据同步问题**
```bash
# 检查BE节点状态
mysql -h127.0.0.1 -P9030 -uroot -e "SHOW BACKENDS;"
# 检查表状态
mysql -h127.0.0.1 -P9030 -uroot -e "SHOW TABLES FROM demo;"
```
3. **性能问题**
- 检查查询计划: `EXPLAIN SELECT ...`
- 监控资源使用: 访问 http://localhost:8030
- 优化SQL语句和索引
### 日志查看
```bash
# 查看应用日志
docker-compose logs -f app
# 查看StarRocks FE日志
docker-compose logs -f starrocks-fe
# 查看StarRocks BE日志
docker-compose logs -f starrocks-be
# 查看MySQL日志
docker-compose logs -f mysql
```
## 📚 相关文档
- [StarRocks官方文档](https://docs.starrocks.io/)
- [MySQL官方文档](https://dev.mysql.com/doc/)
- [Spring Boot多数据源配置](https://spring.io/guides/gs/accessing-data-mysql/)
- [MyBatis官方文档](https://mybatis.org/mybatis-3/)
## 🤝 贡献
欢迎提交Issue和Pull Request来改进这个项目!
## 📄 许可证
本项目采用MIT许可证。
\ No newline at end of file
version: '3.8'
services:
# MySQL 数据库
# mysql:
# image: mysql:5.7
# container_name: mysql-db
# restart: always
# environment:
# MYSQL_ROOT_PASSWORD: 123456
# MYSQL_DATABASE: road-map
# MYSQL_USER: app
# MYSQL_PASSWORD: 123456
# ports:
# - "3306:3306"
# volumes:
# - mysql_data:/var/lib/mysql
# - ./docker/mysql/init:/docker-entrypoint-initdb.d
# command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
# networks:
# - app-network
# StarRocks FE (Frontend)
starrocks-fe:
image: starrocks/fe-ubuntu:3.1-latest
container_name: starrocks-fe
hostname: starrocks-fe
restart: always
environment:
- FE_SERVERS=fe1:starrocks-fe:9010
- FE_ID=1
ports:
- "8030:8030" # Web UI
- "9020:9020" # RPC port
- "9030:9030" # MySQL protocol port
volumes:
- fe_data:/opt/starrocks/fe/meta
- ./docker/starrocks/fe.conf:/opt/starrocks/fe/conf/fe.conf
networks:
- app-network
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8030 || exit 1"]
interval: 30s
timeout: 10s
retries: 3
# StarRocks BE (Backend)
starrocks-be:
image: starrocks/be-ubuntu:3.1-latest
container_name: starrocks-be
hostname: starrocks-be
restart: always
depends_on:
starrocks-fe:
condition: service_healthy
environment:
- FE_SERVERS=starrocks-fe:9010
- BE_ADDR=starrocks-be:9050
ports:
- "8040:8040" # Web UI
- "9050:9050" # Heartbeat port
- "8060:8060" # Brpc port
volumes:
- be_data:/opt/starrocks/be/storage
- ./docker/starrocks/be.conf:/opt/starrocks/be/conf/be.conf
networks:
- app-network
# Redis (可选,用于缓存)
# redis:
# image: redis:7-alpine
# container_name: redis-cache
# restart: always
# ports:
# - "6379:6379"
# volumes:
# - redis_data:/data
# command: redis-server --appendonly yes
# networks:
# - app-network
volumes:
mysql_data:
driver: local
fe_data:
driver: local
be_data:
driver: local
redis_data:
driver: local
networks:
app-network:
driver: bridge
\ No newline at end of file
-- MySQL 初始化脚本
CREATE DATABASE IF NOT EXISTS `road-map` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `road-map`;
-- 创建用户表
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`user_id` varchar(32) NOT NULL COMMENT '用户ID',
`user_name` varchar(64) DEFAULT NULL COMMENT '用户名称',
`user_head` varchar(256) DEFAULT NULL COMMENT '用户头像',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_id` (`user_id`),
KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 插入测试数据
INSERT INTO `user` (`user_id`, `user_name`, `user_head`) VALUES
('10001', '小傅哥', 'https://bugstack.cn/images/article/about/bugstack.png'),
('10002', '小白', 'https://bugstack.cn/images/article/about/bugstack.png'),
('10003', '小黑', 'https://bugstack.cn/images/article/about/bugstack.png'),
('10004', '小红', 'https://bugstack.cn/images/article/about/bugstack.png'),
('10005', '小蓝', 'https://bugstack.cn/images/article/about/bugstack.png');
\ No newline at end of file
# StarRocks BE 配置文件
# 存储路径
storage_root_path = ${STARROCKS_HOME}/storage
# 心跳端口
heartbeat_service_port = 9050
# Brpc端口
brpc_port = 8060
# HTTP端口
be_port = 9060
# Web服务端口
webserver_port = 8040
# 日志配置
LOG_DIR = ${STARROCKS_HOME}/log
sys_log_level = INFO
sys_log_roll_mode = SIZE-MB-1024
sys_log_roll_num = 10
# 内存配置
mem_limit = 90%
chunk_reserved_bytes_limit = 2147483648
# 存储配置
disable_storage_page_cache = false
storage_page_cache_limit = 20%
# 压缩配置
compress_rowbatches = true
# 网络配置
max_client_cache_size_per_host = 10
max_connection_pool_size = 16
# 查询配置
scanner_thread_pool_thread_num = 48
scanner_thread_pool_queue_size = 102400
# 导入配置
push_worker_count_normal_priority = 3
push_worker_count_high_priority = 3
# 副本配置
default_num_rows_per_column_file_block = 1024
# 缓存配置
disable_column_pool = true
# 其他配置
enable_system_metrics = true
enable_prefetch = true
\ No newline at end of file
# StarRocks FE 配置文件
# 日志配置
LOG_DIR = ${STARROCKS_HOME}/log
# 元数据目录
meta_dir = ${STARROCKS_HOME}/meta
# HTTP端口
http_port = 8030
# RPC端口
rpc_port = 9020
# MySQL协议端口
query_port = 9030
# 编辑日志端口
edit_log_port = 9010
# 启用HTTP服务器
enable_http_server_v2 = true
# 系统配置
sys_log_level = INFO
sys_log_roll_mode = SIZE-MB-1024
sys_log_roll_num = 10
# 查询配置
qe_max_connection = 1024
max_conn_per_user = 100
# 内存配置
max_bytes_per_broker_scanner = 3221225472
max_query_retry_time = 2
# 集群配置
cluster_name = StarRocks
cluster_id = 123456
# 认证配置
auth_token = ""
# 副本配置
default_replication_num = 1
# 存储配置
storage_root_path = ${STARROCKS_HOME}/storage
\ No newline at end of file
-- StarRocks 初始化脚本
-- 连接到StarRocks后执行此脚本
-- 创建数据库
CREATE DATABASE IF NOT EXISTS demo;
USE demo;
-- 创建用户表 (StarRocks版本)
DROP TABLE IF EXISTS user;
CREATE TABLE user (
id BIGINT NOT NULL,
user_id VARCHAR(32) NOT NULL,
user_name VARCHAR(64),
user_head VARCHAR(256),
create_time DATETIME,
update_time DATETIME
) ENGINE=OLAP
DUPLICATE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 3
PROPERTIES (
"replication_num" = "1",
"storage_format" = "DEFAULT"
);
-- 插入测试数据
INSERT INTO user (id, user_id, user_name, user_head, create_time, update_time) VALUES
(1, '10001', 'xfg', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-01 10:00:00', '2024-01-01 10:00:00'),
(2, '10002', '小白', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-02 10:00:00', '2024-01-02 10:00:00'),
(3, '10003', '小黑', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-03 10:00:00', '2024-01-03 10:00:00'),
(4, '10004', '小红', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-04 10:00:00', '2024-01-04 10:00:00'),
(5, '10005', '小蓝', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-05 10:00:00', '2024-01-05 10:00:00'),
(6, '10006', '小绿', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-06 10:00:00', '2024-01-06 10:00:00'),
(7, '10007', '小紫', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-07 10:00:00', '2024-01-07 10:00:00'),
(8, '10008', '小黄', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-08 10:00:00', '2024-01-08 10:00:00'),
(9, '10009', '小橙', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-09 10:00:00', '2024-01-09 10:00:00'),
(10, '10010', '小粉', 'https://bugstack.cn/images/article/about/bugstack.png', '2024-01-10 10:00:00', '2024-01-10 10:00:00');
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<!--
| This is the configuration file for Maven. It can be specified at two levels:
|
| 1. User Level. This settings.xml file provides configuration for a single user,
| and is normally provided in ${user.home}/.m2/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -s /path/to/user/settings.xml
|
| 2. Global Level. This settings.xml file provides configuration for all Maven
| users on a machine (assuming they're all using the same Maven
| installation). It's normally provided in
| ${maven.conf}/settings.xml.
|
| NOTE: This location can be overridden with the CLI option:
|
| -gs /path/to/global/settings.xml
|
| The sections in this sample file are intended to give you a running start at
| getting the most out of your Maven installation. Where appropriate, the default
| values (values used when the setting is not specified) are provided.
|
|-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
<!-- localRepository
| The path to the local repository maven will use to store artifacts.
|
| Default: ${user.home}/.m2/repository
<localRepository>/path/to/local/repo</localRepository>
-->
<localRepository>/Users/fuzhengwei/Applications/apache-maven-3.8.4/repository</localRepository>
<!-- interactiveMode
| This will determine whether maven prompts you when it needs input. If set to false,
| maven will use a sensible default value, perhaps based on some other setting, for
| the parameter in question.
|
| Default: true
<interactiveMode>true</interactiveMode>
-->
<!-- offline
| Determines whether maven should attempt to connect to the network when executing a build.
| This will have an effect on artifact downloads, artifact deployment, and others.
|
| Default: false
<offline>false</offline>
-->
<!-- pluginGroups
| This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
| when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
| "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
|-->
<pluginGroups>
<!-- pluginGroup
| Specifies a further group identifier to use for plugin lookup.
<pluginGroup>com.your.plugins</pluginGroup>
-->
</pluginGroups>
<!-- proxies
| This is a list of proxies which can be used on this machine to connect to the network.
| Unless otherwise specified (by system property or command-line switch), the first proxy
| specification in this list marked as active will be used.
|-->
<proxies>
<!-- proxy
| Specification for one proxy, to be used in connecting to the network.
|
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
-->
</proxies>
<!-- servers
| This is a list of authentication profiles, keyed by the server-id used within the system.
| Authentication profiles can be used whenever maven must make a connection to a remote server.
|-->
<servers>
<!-- server
| Specifies the authentication information to use when connecting to a particular server, identified by
| a unique name within the system (referred to by the 'id' attribute below).
|
| NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
| used together.
|
<server>
<id>deploymentRepo</id>
<username>repouser</username>
<password>repopwd</password>
</server>
-->
<!-- Another sample, using keys to authenticate.
<server>
<id>siteServer</id>
<privateKey>/path/to/private/key</privateKey>
<passphrase>optional; leave empty if not used.</passphrase>
</server>
-->
</servers>
<!-- mirrors
| This is a list of mirrors to be used in downloading artifacts from remote repositories.
|
| It works like this: a POM may declare a repository to use in resolving certain artifacts.
| However, this repository may have problems with heavy traffic at times, so people have mirrored
| it to several places.
|
| That repository definition will have a unique id, so we can create a mirror reference for that
| repository, to be used as an alternate download site. The mirror site will be the preferred
| server for that repository.
|-->
<mirrors>
<!-- mirror
| Specifies a repository mirror site to use instead of a given repository. The repository that
| this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
| for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
|
<mirror>
<id>mirrorId</id>
<mirrorOf>repositoryId</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://my.repository.com/repo/path</url>
</mirror>
-->
<mirror>
<id>alimaven</id>
<mirrorOf>central</mirrorOf>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/nexus/content/repositories/central/</url>
</mirror>
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>
</mirrors>
<!-- profiles
| This is a list of profiles which can be activated in a variety of ways, and which can modify
| the build process. Profiles provided in the settings.xml are intended to provide local machine-
| specific paths and repository locations which allow the build to work in the local environment.
|
| For example, if you have an integration testing plugin - like cactus - that needs to know where
| your Tomcat instance is installed, you can provide a variable here such that the variable is
| dereferenced during the build process to configure the cactus plugin.
|
| As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
| section of this document (settings.xml) - will be discussed later. Another way essentially
| relies on the detection of a system property, either matching a particular value for the property,
| or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
| value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
| Finally, the list of active profiles can be specified directly from the command line.
|
| NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
| repositories, plugin repositories, and free-form properties to be used as configuration
| variables for plugins in the POM.
|
|-->
<profiles>
<!-- profile
| Specifies a set of introductions to the build process, to be activated using one or more of the
| mechanisms described above. For inheritance purposes, and to activate profiles via <activatedProfiles/>
| or the command line, profiles have to have an ID that is unique.
|
| An encouraged best practice for profile identification is to use a consistent naming convention
| for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', 'user-brett', etc.
| This will make it more intuitive to understand what the set of introduced profiles is attempting
| to accomplish, particularly when you only have a list of profile id's for debug.
|
| This profile example uses the JDK version to trigger activation, and provides a JDK-specific repo.
<profile>
<id>jdk-1.4</id>
<activation>
<jdk>1.4</jdk>
</activation>
<repositories>
<repository>
<id>jdk14</id>
<name>Repository for JDK 1.4 builds</name>
<url>http://www.myhost.com/maven/jdk14</url>
<layout>default</layout>
<snapshotPolicy>always</snapshotPolicy>
</repository>
</repositories>
</profile>
-->
<!--
| Here is another profile, activated by the system property 'target-env' with a value of 'dev',
| which provides a specific path to the Tomcat instance. To use this, your plugin configuration
| might hypothetically look like:
|
| ...
| <plugin>
| <groupId>org.myco.myplugins</groupId>
| <artifactId>myplugin</artifactId>
|
| <configuration>
| <tomcatLocation>${tomcatPath}</tomcatLocation>
| </configuration>
| </plugin>
| ...
|
| NOTE: If you just wanted to inject this configuration whenever someone set 'target-env' to
| anything, you could just leave off the <value/> inside the activation-property.
|
<profile>
<id>env-dev</id>
<activation>
<property>
<name>target-env</name>
<value>dev</value>
</property>
</activation>
<properties>
<tomcatPath>/path/to/tomcat/instance</tomcatPath>
</properties>
</profile>
-->
</profiles>
<!-- activeProfiles
| List of profiles that are active for all builds.
|
<activeProfiles>
<activeProfile>alwaysActiveProfile</activeProfile>
<activeProfile>anotherAlwaysActiveProfile</activeProfile>
</activeProfiles>
-->
</settings>
<mxfile host="Electron" modified="2023-06-23T03:01:46.233Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.2.8 Chrome/102.0.5005.167 Electron/19.0.15 Safari/537.36" etag="81cllX9HgDdVc98kTfrO" version="20.2.8" type="device" pages="3"><diagram id="c9HScdntACTEwCYFckSf" name="1. 问题">7Vpdc9o4FP01ekxHtmQhP9pgmpltpp3Snab7kjG2MN4aizUigf31e2XLwcZOGmYgsB14Qbqyvu655+oYgchwsflYhMv5nYxFhmwcbxAZIdu2LM7gS1u2lWVABpUhKdK4MuGdYZL+K0zP2rpOY7EytsqkpMxUumwbI5nnIlItW1gU8qn92ExmccuwDBPRMUyiMOtav6exmldWF+Od/VakybyemdUti7B+2BhW8zCWTw0TCRAZFlKqqrTYDEWmndf2y/iF1ueFFSJXb+nw8Wt4UwTFH3/dWV8/3T98zrKZe0MMPI9htjY7NqtV29oFMAx4Gyr+0zxVYrIMI93yBICDba4WGdQsKIarZQXBLN0ImNWfyVyNw0WaafCHcpFGMPIkzFfwdTcxDxjMbQp1sxhRKLF5cZvWs/Mg6oRcCFVs4RHTgRH2wak6mZAj3AzytAOQupVp3sCutoUmZJLnsXdehYJx7CFOdn43J1OKL8zF9Hdzse3gS4vjvlzBMpjVn0IhUeXGK4N2SMv77J+1rBtuVqWrPHjAYstN1c20Pw8UDJA/RC7TBY8j7hMUMOSNkOfUk8Amqnnac4O5sZ69IABA1B7aWZrkUI4AGFGAQcOWwgngmYZFGse6u18IWHg4LYfCUF/KNFelkx0fOSM91lrJanPl0CtVyJ9iKDMJ445ymetRZmmW7Zt24WPRt8TbEeLLwrQVXdQhdbw14mvAuvFFrBPFl8U6cBVynceag6XDZaHmMpF5mH2Scmmc/LdQamu8p/3fRldsUnXfKP/QQ8FGq9poY0YuK1tTOYTusOYaDhF3pMQeGLA1uS4i8ZoPiBE5YZEI9dqDtB/eQmShSh/bKzk+VKSbCwIHeQFyPRRQ5LuIu9riW8gNNHM5Rt7gFXytX+flg3Che1RDNhEk4rgGuGHH5afDV2jxseuULcdI6FY7nVPaTedWLRabfGP4VCC+hsc78g0cWGzvm5VGL13ddStrF8FT+laeOmflaY8uAlZyjly/pKePfE/TEw5a4CwU4Jx1nfPyFGMe9vF0Vn76eIqxMzgWTynml8bTnveHgCMfI060PHKpVkgm2TqlYKIa1vMmW8eih4Ho2yYNHwFEhq1LA5H3guiNkT8oeWchXp2h45KJXFs867wgaqggV/SARRhxSXyak9EhbwSLnOpNx3L7GTfWXAOMIHlqVXMFC8DigzODVU/Wo0WDUouOkEuuYJXZjZJzg2X1ggWnlcaIa1yqs+wKFnPdc4Nl94DFNK3MWx6gc02D1Q8lTvfHk3cGq++VnGlBCEJRv4CPdErcce2yNH/sCB7TPtS4PSWMHQe1fW1/fqVhv/CCBhiNNaFA4cP5dQXrMpRGV8Pffvv2BSwlwQL927QGb4w8cuYkyCMRRX0ITblDnRO9ZZ2fTqRHXhx4JWHTF64krBfvHf5vdwzsne4YIEA6d1jdY9Luu8M61Q9ipEfSHCtA7GuAHJriKf9leBDynuHRI6KOFR7kGh6Hni+UviF/nCpAkj/Z5x/T5Iv18Phdrm9HxWT0cNM9X6brZKXC6OeHKEcUlwIbawmghYCNeKkIQG97Xc128Tjb74Sz4zp7OA8Y7yqJ+nBvAm2zg4GG6u5fV2Vb479rJPgP</diagram><diagram id="Qjllg6JF8vO2Y3taFBXO" name="2. 架构">7Zrbdps6EIafRpfNEhIH6RIcu+1eyWqz3EN6qYBis4ORi+XE3k+/RyBiMLRNWrukTXIRSyMJi/l+aQYZREeLzetCLOfnKpEZIjjZIHqKCHGow+DDWLaVhTm8MsyKNKlMeGeYpv9JO7K2rtNErqytMmmlMp0u28ZY5bmMdcsmikLdtbtdqyxpGZZiJlvTMIZpLDLZ6fY5TfS8snLc6P1GprN5/c1+3bIQdWdrWM1Fou4aJjpGdFQopavSYjOSmXFe2y+Tb7TeT6yQuX7IgMXHm/nn5bsp3uD3766jC3HxKXtVu3mlt/UdywQcYKuq0HM1U7nIxjtrVKh1nkhzWQy1XZ8zpZZgdMD4r9R6a2mKtVZgmutFZlvlJtWXjfIXc6kTz9ZON/bKZWVbV3JdbC+blcYoU90NK2v1uGuV64lYpJkxjNQijeF2pyJfwcf51HawM3VcqFcOMV74pqOtaaXWRSy/510rWFHMpP5OP3IvB1hHUi0k3ACMK2QmdHrbnoewgp7d99sxh4LF/hgJOC8SGF4C3qASIC8SGF4CdFAJ0D9FAn8CSndQlNV1b0W2tt+EiJ9p65kWY//rWtUNr1alz0Lo4LjLTem4ut1kTiJuj+m6vtHdn5nP809wBxiNPcQYYr4pRA5iBI19xMco8m2BufUM4YarSVYX6Ghypzgjmbt5quV0Wc3sDhLQtrpWN1LHc1uxTpGFlpvv66DLzQ6AOyhH2FSWurZ+t0sMnTrbmzeSQh8fiTTpkB6B8wqVZbL4Ndc9epFdp1k2Upkqyi+jksYM16u1Ycfln2ED07yRjZYIc69sOQAoit0WKYcHA5OiHVKJUMMiwpiJPkTX5V8fIoy94FiICGcDI3K7iNRCpPmwlJwr4UjyOEr+OJwchxLlfGBKXofSSha3KXh/2P3Oc9zHLaaI2J3wCJi8+hBiMEx+NweBUM/GKAxsOhA104EJikaIjeo+XtlngkKKxgHioUkQwBKOTbIAFugTdQ8uwH+6TVVk6SyHcgx+hIhII+PlNBZZaBsWaZJUmayE7EdclZcyUJYqzXXpFC9C3qm5FiSvKyuADs9c5XJPFLVpXzcPEpq9KecA2iCctGOh17OEXberDcKPpI2gVxvcM0yNAE4N6B5tgCVEHCTBUOigkDW0wcyQaILGHEGoh/KLNn5GG8QfWhusRxuw8EED3FAGSQD6Xm3s99nbN0I0dk0Hxl+08VPaoEFPTPmt2uD9+8bI7BgmXoTf0AZAxyiKSm2AErraeIkpv6gNN3B+nzaCZPTP2zP/4/WXG7yYbNiX5Gzbd+ZhggJoIDAisZLo7BKD5owmM4REqCc3pD7lNDlMbuh6tM0K8xPvYdkhPRat7rlFiWSCeLkmeVSuyedIy8fkydHqnl00Nk4IqqdlUvYcaQWe8+RodY8x+jLn50jr/kf7J0Sre5xhj8RtwlqmLM+SloNd/uRw9R9r9Dy6VssNmvySG/ynptug3BJPssTt48bIFfX94+QbFLPBsfWdOJQPDHxi1hSjJoi90IKS5+DBaXXPAN58+PAeEdxzPDjsRshiGcd9iK6Y53oHOtzdR0RwMDii+rWx1m/MeyhWc7E0xXhdZNuoEPGN+cn8R0zaAB9DiLjlcC10qsxz+Ct+IAC+59YOrxHUSJoAvK7/Xcc/FoCeR6i/FgD3yB4At35M+gEAx7kPPodH0PNc9NcicBxMToI2BMqDe9OPOBziZZe3c6bTWcDiuw+j2eX08uLt4mvPwc/VerbS4OmTOEdu+fIJJGcQLUzMIIiVwQOSs7Ab35/8YR95iBwOQRtT1k4LCO2LOdTpoiaP3/KgunsNumxrvExOx/8D</diagram><diagram id="IbJuPW5fwbRyof4lrsmB" name="3. 流程">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</diagram></mxfile>
\ No newline at end of file
package cn.bugstack.xfg.frame.common;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {
@Builder
public class Result<T> {
private String code;
private String info;
private T data;
public static Result buildSuccess() {
return new Result(Constants.ResponseCode.SUCCESS.getCode(), Constants.ResponseCode.SUCCESS.getInfo());
return new Result(Constants.ResponseCode.SUCCESS.getCode(), Constants.ResponseCode.SUCCESS.getInfo(), null);
}
public static Result buildFail() {
return new Result(Constants.ResponseCode.UN_ERROR.getCode(), Constants.ResponseCode.UN_ERROR.getInfo());
return new Result(Constants.ResponseCode.UN_ERROR.getCode(), Constants.ResponseCode.UN_ERROR.getInfo(), null);
}
public static <T> Result<T> buildSuccess(T data) {
return new Result<>(Constants.ResponseCode.SUCCESS.getCode(), Constants.ResponseCode.SUCCESS.getInfo(), data);
}
public static <T> Result<T> buildFail(String info) {
return new Result<>(Constants.ResponseCode.UN_ERROR.getCode(), info, null);
}
}
package cn.bugstack.xfg.frame.config;
import com.zaxxer.hikari.HikariDataSource;
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.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* 双数据源配置类
* 支持MySQL和StarRocks双数据源
*/
@Configuration
public class DataSourceConfig {
/**
* MySQL数据源配置
*/
@Primary
@Bean(name = "mysqlDataSource")
@ConfigurationProperties(prefix = "spring.datasource.mysql")
public DataSource mysqlDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
/**
* StarRocks数据源配置
*/
@Bean(name = "starrocksDataSource")
@ConfigurationProperties(prefix = "spring.datasource.starrocks")
public DataSource starrocksDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
/**
* MySQL SqlSessionFactory
*/
@Primary
@Bean(name = "mysqlSqlSessionFactory")
public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mybatis/mapper/*_Mapper.xml"));
bean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:/mybatis/config/mybatis-config.xml"));
return bean.getObject();
}
/**
* StarRocks SqlSessionFactory
*/
@Bean(name = "starrocksSqlSessionFactory")
public SqlSessionFactory starrocksSqlSessionFactory(@Qualifier("starrocksDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mybatis/mapper/StarRocks_*_Mapper.xml"));
bean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:/mybatis/config/mybatis-config.xml"));
return bean.getObject();
}
/**
* MySQL SqlSessionTemplate
*/
@Primary
@Bean(name = "mysqlSqlSessionTemplate")
public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* StarRocks SqlSessionTemplate
*/
@Bean(name = "starrocksSqlSessionTemplate")
public SqlSessionTemplate starrocksSqlSessionTemplate(@Qualifier("starrocksSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
/**
* MySQL JdbcTemplate
*/
@Primary
@Bean(name = "mysqlJdbcTemplate")
public JdbcTemplate mysqlJdbcTemplate(@Qualifier("mysqlDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
/**
* StarRocks JdbcTemplate
*/
@Bean(name = "starrocksJdbcTemplate")
public JdbcTemplate starrocksJdbcTemplate(@Qualifier("starrocksDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
/**
* MySQL事务管理器
*/
@Primary
@Bean(name = "mysqlTransactionManager")
public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* StarRocks事务管理器
*/
@Bean(name = "starrocksTransactionManager")
public DataSourceTransactionManager starrocksTransactionManager(@Qualifier("starrocksDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* MySQL Mapper扫描配置
*/
@Configuration
@MapperScan(basePackages = "cn.bugstack.xfg.frame.dao", sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
static class MySQLMapperScanConfig {
}
/**
* StarRocks Mapper扫描配置
*/
@Configuration
@MapperScan(basePackages = "cn.bugstack.xfg.frame.dao.starrocks", sqlSessionTemplateRef = "starrocksSqlSessionTemplate")
static class StarRocksMapperScanConfig {
}
}
\ No newline at end of file
package cn.bugstack.xfg.frame.controller;
import cn.bugstack.xfg.frame.common.Result;
import cn.bugstack.xfg.frame.domain.po.User;
import cn.bugstack.xfg.frame.domain.vo.UserVO;
import cn.bugstack.xfg.frame.service.IStarRocksUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* StarRocks用户控制器
* 提供基本的CRUD REST API接口
*/
@Slf4j
@RestController
@RequestMapping("/api/starrocks/user")
@CrossOrigin("*")
public class StarRocksUserController {
@Resource
private IStarRocksUserService starRocksUserService;
/**
* 查询所有用户
* GET /api/starrocks/user/list
*/
@GetMapping("/list")
public Result<List<UserVO>> queryAllUsers() {
try {
List<UserVO> users = starRocksUserService.queryAllUsers();
return Result.<List<UserVO>>builder()
.code("0000")
.info("查询成功")
.data(users)
.build();
} catch (Exception e) {
log.error("查询所有用户失败", e);
return Result.<List<UserVO>>builder()
.code("0001")
.info("查询失败: " + e.getMessage())
.build();
}
}
/**
* 根据ID查询用户
* GET /api/starrocks/user/{id}
*/
@GetMapping("/{id}")
public Result<UserVO> queryUserById(@PathVariable Long id) {
try {
UserVO user = starRocksUserService.queryUserById(id);
if (user != null) {
return Result.<UserVO>builder()
.code("0000")
.info("查询成功")
.data(user)
.build();
} else {
return Result.<UserVO>builder()
.code("0002")
.info("用户不存在")
.build();
}
} catch (Exception e) {
log.error("根据ID查询用户失败, id: {}", id, e);
return Result.<UserVO>builder()
.code("0001")
.info("查询失败: " + e.getMessage())
.build();
}
}
/**
* 根据用户ID查询用户
* GET /api/starrocks/user/userId/{userId}
*/
@GetMapping("/userId/{userId}")
public Result<UserVO> queryUserByUserId(@PathVariable String userId) {
try {
UserVO user = starRocksUserService.queryUserByUserId(userId);
if (user != null) {
return Result.<UserVO>builder()
.code("0000")
.info("查询成功")
.data(user)
.build();
} else {
return Result.<UserVO>builder()
.code("0002")
.info("用户不存在")
.build();
}
} catch (Exception e) {
log.error("根据用户ID查询用户失败, userId: {}", userId, e);
return Result.<UserVO>builder()
.code("0001")
.info("查询失败: " + e.getMessage())
.build();
}
}
/**
* 创建用户
* POST /api/starrocks/user
*/
@PostMapping
public Result<Boolean> createUser(@RequestBody User user) {
try {
boolean success = starRocksUserService.createUser(user);
if (success) {
return Result.<Boolean>builder()
.code("0000")
.info("创建成功")
.data(true)
.build();
} else {
return Result.<Boolean>builder()
.code("0003")
.info("创建失败")
.data(false)
.build();
}
} catch (Exception e) {
log.error("创建用户失败, user: {}", user, e);
return Result.<Boolean>builder()
.code("0001")
.info("创建失败: " + e.getMessage())
.data(false)
.build();
}
}
/**
* 批量创建用户
* POST /api/starrocks/user/batch
*/
@PostMapping("/batch")
public Result<Boolean> batchCreateUsers(@RequestBody List<User> users) {
try {
boolean success = starRocksUserService.batchCreateUsers(users);
if (success) {
return Result.<Boolean>builder()
.code("0000")
.info("批量创建成功")
.data(true)
.build();
} else {
return Result.<Boolean>builder()
.code("0003")
.info("批量创建失败")
.data(false)
.build();
}
} catch (Exception e) {
log.error("批量创建用户失败, users size: {}", users != null ? users.size() : 0, e);
return Result.<Boolean>builder()
.code("0001")
.info("批量创建失败: " + e.getMessage())
.data(false)
.build();
}
}
/**
* 更新用户
* PUT /api/starrocks/user
*/
@PutMapping
public Result<Boolean> updateUser(@RequestBody User user) {
try {
boolean success = starRocksUserService.updateUser(user);
if (success) {
return Result.<Boolean>builder()
.code("0000")
.info("更新成功")
.data(true)
.build();
} else {
return Result.<Boolean>builder()
.code("0004")
.info("更新失败")
.data(false)
.build();
}
} catch (Exception e) {
log.error("更新用户失败, user: {}", user, e);
return Result.<Boolean>builder()
.code("0001")
.info("更新失败: " + e.getMessage())
.data(false)
.build();
}
}
/**
* 根据ID删除用户
* DELETE /api/starrocks/user/{id}
*/
@DeleteMapping("/{id}")
public Result<Boolean> deleteUserById(@PathVariable Long id) {
try {
boolean success = starRocksUserService.deleteUserById(id);
if (success) {
return Result.<Boolean>builder()
.code("0000")
.info("删除成功")
.data(true)
.build();
} else {
return Result.<Boolean>builder()
.code("0005")
.info("删除失败")
.data(false)
.build();
}
} catch (Exception e) {
log.error("根据ID删除用户失败, id: {}", id, e);
return Result.<Boolean>builder()
.code("0001")
.info("删除失败: " + e.getMessage())
.data(false)
.build();
}
}
/**
* 根据用户ID删除用户
* DELETE /api/starrocks/user/userId/{userId}
*/
@DeleteMapping("/userId/{userId}")
public Result<Boolean> deleteUserByUserId(@PathVariable String userId) {
try {
boolean success = starRocksUserService.deleteUserByUserId(userId);
if (success) {
return Result.<Boolean>builder()
.code("0000")
.info("删除成功")
.data(true)
.build();
} else {
return Result.<Boolean>builder()
.code("0005")
.info("删除失败")
.data(false)
.build();
}
} catch (Exception e) {
log.error("根据用户ID删除用户失败, userId: {}", userId, e);
return Result.<Boolean>builder()
.code("0001")
.info("删除失败: " + e.getMessage())
.data(false)
.build();
}
}
/**
* 查询用户总数
* GET /api/starrocks/user/count
*/
@GetMapping("/count")
public Result<Long> countUsers() {
try {
Long count = starRocksUserService.countUsers();
return Result.<Long>builder()
.code("0000")
.info("查询成功")
.data(count)
.build();
} catch (Exception e) {
log.error("查询用户总数失败", e);
return Result.<Long>builder()
.code("0001")
.info("查询失败: " + e.getMessage())
.build();
}
}
}
\ No newline at end of file
package cn.bugstack.xfg.frame.dao.starrocks;
import cn.bugstack.xfg.frame.domain.po.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* StarRocks用户数据访问接口
* 提供基本的CRUD操作
*/
@Mapper
public interface IStarRocksUserDao {
/**
* 查询所有用户
* @return 用户列表
*/
List<User> queryAllUsers();
/**
* 根据ID查询用户
* @param id 用户ID
* @return 用户信息
*/
User queryUserById(@Param("id") Long id);
/**
* 根据用户ID查询用户
* @param userId 用户ID
* @return 用户信息
*/
User queryUserByUserId(@Param("userId") String userId);
/**
* 插入用户
* @param user 用户信息
* @return 影响行数
*/
int insertUser(User user);
/**
* 批量插入用户
* @param users 用户列表
* @return 影响行数
*/
int batchInsertUsers(@Param("users") List<User> users);
/**
* 更新用户信息
* @param user 用户信息
* @return 影响行数
*/
int updateUser(User user);
/**
* 根据ID删除用户
* @param id 用户ID
* @return 影响行数
*/
int deleteUserById(@Param("id") Long id);
/**
* 根据用户ID删除用户
* @param userId 用户ID
* @return 影响行数
*/
int deleteUserByUserId(@Param("userId") String userId);
/**
* 查询用户总数
* @return 用户总数
*/
Long countUsers();
}
\ No newline at end of file
package cn.bugstack.xfg.frame.service;
import cn.bugstack.xfg.frame.domain.po.User;
import cn.bugstack.xfg.frame.domain.vo.UserVO;
import java.util.List;
/**
* StarRocks用户服务接口
* 提供基本的CRUD操作
*/
public interface IStarRocksUserService {
/**
* 查询所有用户
* @return 用户列表
*/
List<UserVO> queryAllUsers();
/**
* 根据ID查询用户
* @param id 用户ID
* @return 用户信息
*/
UserVO queryUserById(Long id);
/**
* 根据用户ID查询用户
* @param userId 用户ID
* @return 用户信息
*/
UserVO queryUserByUserId(String userId);
/**
* 创建用户
* @param user 用户信息
* @return 是否成功
*/
boolean createUser(User user);
/**
* 批量创建用户
* @param users 用户列表
* @return 是否成功
*/
boolean batchCreateUsers(List<User> users);
/**
* 更新用户信息
* @param user 用户信息
* @return 是否成功
*/
boolean updateUser(User user);
/**
* 根据ID删除用户
* @param id 用户ID
* @return 是否成功
*/
boolean deleteUserById(Long id);
/**
* 根据用户ID删除用户
* @param userId 用户ID
* @return 是否成功
*/
boolean deleteUserByUserId(String userId);
/**
* 查询用户总数
* @return 用户总数
*/
Long countUsers();
}
\ No newline at end of file
package cn.bugstack.xfg.frame.service.impl;
import cn.bugstack.xfg.frame.dao.starrocks.IStarRocksUserDao;
import cn.bugstack.xfg.frame.domain.po.User;
import cn.bugstack.xfg.frame.domain.vo.UserVO;
import cn.bugstack.xfg.frame.service.IStarRocksUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* StarRocks用户服务实现类
*/
@Slf4j
@Service
public class StarRocksUserServiceImpl implements IStarRocksUserService {
@Resource
private IStarRocksUserDao starRocksUserDao;
@Override
public List<UserVO> queryAllUsers() {
try {
List<User> users = starRocksUserDao.queryAllUsers();
return users.stream().map(this::convertToVO).collect(Collectors.toList());
} catch (Exception e) {
log.error("查询所有用户失败", e);
throw new RuntimeException("查询所有用户失败", e);
}
}
@Override
public UserVO queryUserById(Long id) {
try {
User user = starRocksUserDao.queryUserById(id);
return user != null ? convertToVO(user) : null;
} catch (Exception e) {
log.error("根据ID查询用户失败, id: {}", id, e);
throw new RuntimeException("根据ID查询用户失败", e);
}
}
@Override
public UserVO queryUserByUserId(String userId) {
try {
User user = starRocksUserDao.queryUserByUserId(userId);
return user != null ? convertToVO(user) : null;
} catch (Exception e) {
log.error("根据用户ID查询用户失败, userId: {}", userId, e);
throw new RuntimeException("根据用户ID查询用户失败", e);
}
}
@Override
public boolean createUser(User user) {
try {
// 设置创建时间和更新时间
Date now = new Date();
user.setCreateTime(now);
user.setUpdateTime(now);
int result = starRocksUserDao.insertUser(user);
return result > 0;
} catch (Exception e) {
log.error("创建用户失败, user: {}", user, e);
throw new RuntimeException("创建用户失败", e);
}
}
@Override
public boolean batchCreateUsers(List<User> users) {
try {
if (users == null || users.isEmpty()) {
return false;
}
// 设置创建时间和更新时间
Date now = new Date();
users.forEach(user -> {
user.setCreateTime(now);
user.setUpdateTime(now);
});
int result = starRocksUserDao.batchInsertUsers(users);
return result > 0;
} catch (Exception e) {
log.error("批量创建用户失败, users size: {}", users != null ? users.size() : 0, e);
throw new RuntimeException("批量创建用户失败", e);
}
}
@Override
public boolean updateUser(User user) {
try {
// 设置更新时间
user.setUpdateTime(new Date());
int result = starRocksUserDao.updateUser(user);
return result > 0;
} catch (Exception e) {
log.error("更新用户失败, user: {}", user, e);
throw new RuntimeException("更新用户失败", e);
}
}
@Override
public boolean deleteUserById(Long id) {
try {
int result = starRocksUserDao.deleteUserById(id);
return result > 0;
} catch (Exception e) {
log.error("根据ID删除用户失败, id: {}", id, e);
throw new RuntimeException("根据ID删除用户失败", e);
}
}
@Override
public boolean deleteUserByUserId(String userId) {
try {
int result = starRocksUserDao.deleteUserByUserId(userId);
return result > 0;
} catch (Exception e) {
log.error("根据用户ID删除用户失败, userId: {}", userId, e);
throw new RuntimeException("根据用户ID删除用户失败", e);
}
}
@Override
public Long countUsers() {
try {
return starRocksUserDao.countUsers();
} catch (Exception e) {
log.error("查询用户总数失败", e);
throw new RuntimeException("查询用户总数失败", e);
}
}
/**
* 将User PO转换为UserVO
*/
private UserVO convertToVO(User user) {
UserVO userVO = new UserVO();
userVO.setUserId(user.getUserId());
userVO.setUserNickname(user.getUserNickname());
userVO.setCreateTime(user.getCreateTime());
return userVO;
}
}
\ No newline at end of file
......@@ -3,14 +3,45 @@ server:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.jdbc.Driver
# MySQL数据源配置
mysql:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: MySQLHikariCP
minimum-idle: 5
maximum-pool-size: 20
auto-commit: true
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
# StarRocks数据源配置
starrocks:
username: root
password:
url: jdbc:mysql://127.0.0.1:9030/demo?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: StarRocksHikariCP
minimum-idle: 3
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
lazy-loading-enabled: true
# RagFlow 配置
ragflow:
......
<?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="cn.bugstack.xfg.frame.dao.starrocks.IStarRocksUserDao">
<!-- 用户结果映射 -->
<resultMap id="userMap" type="cn.bugstack.xfg.frame.domain.po.User">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="user_name" property="userNickname"/>
<result column="user_head" property="userHead"/>
<result column="user_password" property="userPassword"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 查询所有用户 -->
<select id="queryAllUsers" resultMap="userMap">
SELECT id, user_id, user_name, user_head, user_password, create_time, update_time
FROM user
ORDER BY id
</select>
<!-- 根据ID查询用户 -->
<select id="queryUserById" parameterType="java.lang.Long" resultMap="userMap">
SELECT id, user_id, user_name, user_head, user_password, create_time, update_time
FROM user
WHERE id = #{id}
</select>
<!-- 根据用户ID查询用户 -->
<select id="queryUserByUserId" parameterType="java.lang.String" resultMap="userMap">
SELECT id, user_id, user_name, user_head, user_password, create_time, update_time
FROM user
WHERE user_id = #{userId}
</select>
<!-- 插入用户 -->
<insert id="insertUser" parameterType="cn.bugstack.xfg.frame.domain.po.User">
INSERT INTO user (id, user_id, user_name, user_head, user_password, create_time, update_time)
VALUES (#{id}, #{userId}, #{userNickname}, #{userHead}, #{userPassword}, #{createTime}, #{updateTime})
</insert>
<!-- 批量插入用户 -->
<insert id="batchInsertUsers" parameterType="java.util.List">
INSERT INTO user (id, user_id, user_name, user_head, user_password, create_time, update_time)
VALUES
<foreach collection="users" item="user" separator=",">
(#{user.id}, #{user.userId}, #{user.userNickname}, #{user.userHead}, #{user.userPassword}, #{user.createTime}, #{user.updateTime})
</foreach>
</insert>
<!-- 更新用户信息 -->
<update id="updateUser" parameterType="cn.bugstack.xfg.frame.domain.po.User">
UPDATE user
<set>
<if test="userId != null and userId != ''">
user_id = #{userId},
</if>
<if test="userNickname != null and userNickname != ''">
user_name = #{userNickname},
</if>
<if test="userHead != null and userHead != ''">
user_head = #{userHead},
</if>
<if test="userPassword != null and userPassword != ''">
user_password = #{userPassword},
</if>
<if test="updateTime != null">
update_time = #{updateTime}
</if>
</set>
WHERE id = #{id}
</update>
<!-- 根据ID删除用户 -->
<delete id="deleteUserById" parameterType="java.lang.Long">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 根据用户ID删除用户 -->
<delete id="deleteUserByUserId" parameterType="java.lang.String">
DELETE FROM user WHERE user_id = #{userId}
</delete>
<!-- 查询用户总数 -->
<select id="countUsers" resultType="java.lang.Long">
SELECT COUNT(*) FROM user
</select>
</mapper>
\ No newline at end of file
你是一个专业的客服助手,致力于为客户提供优质的服务体验。
你的服务理念:
- 客户至上,服务第一
- 耐心、友好、专业
- 快速响应,高效解决问题
- 主动关怀,超越期望
你的职责:
1. 热情接待每一位客户
2. 仔细倾听客户的需求和问题
3. 从知识库中查找相关的服务信息
4. 提供准确、及时的解答和帮助
5. 跟进问题解决情况,确保客户满意
服务要求:
- 使用礼貌、友好的语言
- 保持耐心,即使面对困难客户
- 提供清晰、易懂的解答
- 主动提供额外的帮助和建议
- 如果无法解决,及时转接相关部门
以下是客服知识库内容:
{knowledge}
以上是客服知识库内容。
请基于以上知识库内容,为客户提供优质的服务。记住,你的目标是让每一位客户都感到满意和被重视。
\ No newline at end of file
你是一个智能的通用助手,请根据知识库内容来回答问题。
你的职责:
1. 仔细分析用户的问题
2. 从提供的知识库中寻找相关信息
3. 基于知识库内容给出准确、有用的回答
4. 如果知识库中没有相关信息,请诚实地告知用户
回答要求:
- 回答要准确、简洁、有条理
- 优先使用知识库中的信息
- 保持友好和专业的语调
- 如果需要,可以要求用户提供更多信息
以下是知识库内容:
{knowledge}
以上是知识库内容。
请基于以上知识库内容回答用户的问题。
\ No newline at end of file
你是一个专业的技术助手,专门解答技术相关问题。
你的专业领域:
- 软件开发和编程
- 系统架构和设计
- 技术问题诊断和解决
- 最佳实践和代码优化
- 技术文档和规范
你的职责:
1. 深入理解用户的技术问题
2. 从知识库中查找相关的技术信息
3. 提供详细、准确的技术解答
4. 给出实用的代码示例或解决方案
5. 推荐最佳实践和优化建议
回答要求:
- 技术回答要准确、详细
- 提供具体的代码示例(如果适用)
- 解释技术原理和实现思路
- 考虑性能、安全性和可维护性
- 如果涉及多种解决方案,请比较优缺点
以下是技术知识库内容:
{knowledge}
以上是技术知识库内容。
请基于以上技术知识库内容,为用户提供专业的技术解答。
\ No newline at end of file
#!/bin/bash
# StarRocks + MySQL 双数据源环境启动脚本
echo "🚀 启动 StarRocks + MySQL 双数据源环境..."
# 检查Docker是否运行
if ! docker info > /dev/null 2>&1; then
echo "❌ Docker未运行,请先启动Docker"
exit 1
fi
# 启动所有服务
echo "📦 启动Docker Compose服务..."
docker-compose up -d
# 等待服务启动
echo "⏳ 等待服务启动..."
sleep 30
# 检查MySQL服务
echo "🔍 检查MySQL服务..."
until docker-compose exec mysql mysqladmin ping -h"localhost" --silent; do
echo "等待MySQL启动..."
sleep 5
done
echo "✅ MySQL服务已启动"
# 检查StarRocks FE服务
echo "🔍 检查StarRocks FE服务..."
until curl -f http://localhost:8030 > /dev/null 2>&1; do
echo "等待StarRocks FE启动..."
sleep 5
done
echo "✅ StarRocks FE服务已启动"
# 初始化StarRocks数据
echo "📊 初始化StarRocks数据..."
mysql -h127.0.0.1 -P9030 -uroot < docker/starrocks/init-starrocks.sql
echo "🎉 环境启动完成!"
echo ""
echo "📋 服务信息:"
echo " MySQL: http://localhost:3306"
echo " StarRocks FE: http://localhost:8030"
echo " StarRocks Query: mysql://localhost:9030"
echo " Redis: redis://localhost:6379"
echo ""
echo "🔧 测试命令:"
echo " # 测试MySQL连接"
echo " mysql -h127.0.0.1 -P3306 -uroot -p123456 road-map"
echo ""
echo " # 测试StarRocks连接"
echo " mysql -h127.0.0.1 -P9030 -uroot demo"
echo ""
echo "📖 更多信息请查看: README-StarRocks.md"
\ No newline at end of file
......@@ -3,14 +3,45 @@ server:
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=true
driver-class-name: com.mysql.jdbc.Driver
# MySQL数据源配置
mysql:
username: root
password: 123456
url: jdbc:mysql://127.0.0.1:3306/road-map?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: MySQLHikariCP
minimum-idle: 5
maximum-pool-size: 20
auto-commit: true
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
# StarRocks数据源配置
starrocks:
username: root
password:
url: jdbc:mysql://127.0.0.1:9030/demo?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false
driver-class-name: com.mysql.jdbc.Driver
hikari:
pool-name: StarRocksHikariCP
minimum-idle: 3
maximum-pool-size: 15
auto-commit: true
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
connection-test-query: SELECT 1
mybatis:
mapper-locations: classpath:/mybatis/mapper/*.xml
config-location: classpath:/mybatis/config/mybatis-config.xml
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
lazy-loading-enabled: true
# RagFlow 配置
ragflow:
......
<?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="cn.bugstack.xfg.frame.dao.starrocks.IStarRocksUserDao">
<!-- 用户结果映射 -->
<resultMap id="userMap" type="cn.bugstack.xfg.frame.domain.po.User">
<id column="id" property="id"/>
<result column="user_id" property="userId"/>
<result column="user_name" property="userNickname"/>
<result column="user_head" property="userHead"/>
<result column="user_password" property="userPassword"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 查询所有用户 -->
<select id="queryAllUsers" resultMap="userMap">
SELECT id, user_id, user_name, user_head, user_password, create_time, update_time
FROM user
ORDER BY id
</select>
<!-- 根据ID查询用户 -->
<select id="queryUserById" parameterType="java.lang.Long" resultMap="userMap">
SELECT id, user_id, user_name, user_head, user_password, create_time, update_time
FROM user
WHERE id = #{id}
</select>
<!-- 根据用户ID查询用户 -->
<select id="queryUserByUserId" parameterType="java.lang.String" resultMap="userMap">
SELECT id, user_id, user_name, user_head, user_password, create_time, update_time
FROM user
WHERE user_id = #{userId}
</select>
<!-- 插入用户 -->
<insert id="insertUser" parameterType="cn.bugstack.xfg.frame.domain.po.User">
INSERT INTO user (id, user_id, user_name, user_head, user_password, create_time, update_time)
VALUES (#{id}, #{userId}, #{userNickname}, #{userHead}, #{userPassword}, #{createTime}, #{updateTime})
</insert>
<!-- 批量插入用户 -->
<insert id="batchInsertUsers" parameterType="java.util.List">
INSERT INTO user (id, user_id, user_name, user_head, user_password, create_time, update_time)
VALUES
<foreach collection="users" item="user" separator=",">
(#{user.id}, #{user.userId}, #{user.userNickname}, #{user.userHead}, #{user.userPassword}, #{user.createTime}, #{user.updateTime})
</foreach>
</insert>
<!-- 更新用户信息 -->
<update id="updateUser" parameterType="cn.bugstack.xfg.frame.domain.po.User">
UPDATE user
<set>
<if test="userId != null and userId != ''">
user_id = #{userId},
</if>
<if test="userNickname != null and userNickname != ''">
user_name = #{userNickname},
</if>
<if test="userHead != null and userHead != ''">
user_head = #{userHead},
</if>
<if test="userPassword != null and userPassword != ''">
user_password = #{userPassword},
</if>
<if test="updateTime != null">
update_time = #{updateTime}
</if>
</set>
WHERE id = #{id}
</update>
<!-- 根据ID删除用户 -->
<delete id="deleteUserById" parameterType="java.lang.Long">
DELETE FROM user WHERE id = #{id}
</delete>
<!-- 根据用户ID删除用户 -->
<delete id="deleteUserByUserId" parameterType="java.lang.String">
DELETE FROM user WHERE user_id = #{userId}
</delete>
<!-- 查询用户总数 -->
<select id="countUsers" resultType="java.lang.Long">
SELECT COUNT(*) FROM user
</select>
</mapper>
\ No newline at end of file
你是一个专业的客服助手,致力于为客户提供优质的服务体验。
你的服务理念:
- 客户至上,服务第一
- 耐心、友好、专业
- 快速响应,高效解决问题
- 主动关怀,超越期望
你的职责:
1. 热情接待每一位客户
2. 仔细倾听客户的需求和问题
3. 从知识库中查找相关的服务信息
4. 提供准确、及时的解答和帮助
5. 跟进问题解决情况,确保客户满意
服务要求:
- 使用礼貌、友好的语言
- 保持耐心,即使面对困难客户
- 提供清晰、易懂的解答
- 主动提供额外的帮助和建议
- 如果无法解决,及时转接相关部门
以下是客服知识库内容:
{knowledge}
以上是客服知识库内容。
请基于以上知识库内容,为客户提供优质的服务。记住,你的目标是让每一位客户都感到满意和被重视。
\ No newline at end of file
你是一个智能的通用助手,请根据知识库内容来回答问题。
你的职责:
1. 仔细分析用户的问题
2. 从提供的知识库中寻找相关信息
3. 基于知识库内容给出准确、有用的回答
4. 如果知识库中没有相关信息,请诚实地告知用户
回答要求:
- 回答要准确、简洁、有条理
- 优先使用知识库中的信息
- 保持友好和专业的语调
- 如果需要,可以要求用户提供更多信息
以下是知识库内容:
{knowledge}
以上是知识库内容。
请基于以上知识库内容回答用户的问题。
\ No newline at end of file
你是一个专业的技术助手,专门解答技术相关问题。
你的专业领域:
- 软件开发和编程
- 系统架构和设计
- 技术问题诊断和解决
- 最佳实践和代码优化
- 技术文档和规范
你的职责:
1. 深入理解用户的技术问题
2. 从知识库中查找相关的技术信息
3. 提供详细、准确的技术解答
4. 给出实用的代码示例或解决方案
5. 推荐最佳实践和优化建议
回答要求:
- 技术回答要准确、详细
- 提供具体的代码示例(如果适用)
- 解释技术原理和实现思路
- 考虑性能、安全性和可维护性
- 如果涉及多种解决方案,请比较优缺点
以下是技术知识库内容:
{knowledge}
以上是技术知识库内容。
请基于以上技术知识库内容,为用户提供专业的技术解答。
\ No newline at end of file
#!/bin/bash
# StarRocks API 测试脚本
BASE_URL="http://localhost:8089/api/starrocks/user"
echo "🧪 StarRocks API 测试脚本"
echo "=========================="
# 测试查询所有用户
echo "📋 1. 查询所有用户"
curl -s -X GET "$BASE_URL/list" | jq '.'
echo ""
# 测试查询用户总数
echo "📊 2. 查询用户总数"
curl -s -X GET "$BASE_URL/count" | jq '.'
echo ""
# 测试根据ID查询用户
echo "🔍 3. 根据ID查询用户 (ID: 1)"
curl -s -X GET "$BASE_URL/1" | jq '.'
echo ""
# 测试根据用户ID查询用户
echo "🔍 4. 根据用户ID查询用户 (userId: 10001)"
curl -s -X GET "$BASE_URL/userId/10001" | jq '.'
echo ""
# 测试创建用户
echo "➕ 5. 创建新用户"
curl -s -X POST "$BASE_URL" \
-H "Content-Type: application/json" \
-d '{
"id": 100,
"userId": "test001",
"userNickname": "测试用户",
"userHead": "https://example.com/avatar.png",
"userPassword": "password123"
}' | jq '.'
echo ""
# 测试批量创建用户
echo "➕ 6. 批量创建用户"
curl -s -X POST "$BASE_URL/batch" \
-H "Content-Type: application/json" \
-d '[
{
"id": 101,
"userId": "test002",
"userNickname": "批量用户1",
"userHead": "https://example.com/avatar1.png"
},
{
"id": 102,
"userId": "test003",
"userNickname": "批量用户2",
"userHead": "https://example.com/avatar2.png"
}
]' | jq '.'
echo ""
# 测试更新用户
echo "✏️ 7. 更新用户信息"
curl -s -X PUT "$BASE_URL" \
-H "Content-Type: application/json" \
-d '{
"id": 100,
"userId": "test001",
"userNickname": "更新后的测试用户",
"userHead": "https://example.com/new-avatar.png"
}' | jq '.'
echo ""
# 测试删除用户
echo "🗑️ 8. 删除用户 (ID: 102)"
curl -s -X DELETE "$BASE_URL/102" | jq '.'
echo ""
# 测试根据用户ID删除用户
echo "🗑️ 9. 根据用户ID删除用户 (userId: test003)"
curl -s -X DELETE "$BASE_URL/userId/test003" | jq '.'
echo ""
# 再次查询所有用户,验证操作结果
echo "📋 10. 最终用户列表"
curl -s -X GET "$BASE_URL/list" | jq '.'
echo ""
echo "✅ API测试完成!"
\ No newline at end of file
......@@ -6,7 +6,7 @@
# https://github.com/sequelpro/sequelpro
#
# Host: 127.0.0.1 (MySQL 5.7.10)
# Database: xfg-frame
# Database: lzr-frame
# Generation Time: 2023-06-22 22:20:33 +0000
# ************************************************************
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册