基于 Spring Boot + JPA + MySQL 的上门家政系统核心功能示例代码

简介: 这是一个基于Spring Boot + JPA + MySQL的上门家政系统核心示例,涵盖用户、服务人员、服务项目及订单管理四大模块。代码结构清晰,含实体类、Repository、Service、Controller及DTO,支持下单、时间冲突检测、状态流转与评价功能,可快速扩展为完整应用。

以下是一个基于 Spring Boot + JPA + MySQL 的上门家政系统核心功能示例代码,涵盖了用户、服务人员、服务项目、订单管理的典型实现。

项目结构

src/main/java/com/housekeeping/
├── entity/
│   ├── User.java
│   ├── Staff.java
│   ├── ServiceItem.java
│   ├── Order.java
│   └── OrderStatus.java
├── repository/
│   ├── UserRepository.java
│   ├── StaffRepository.java
│   ├── ServiceItemRepository.java
│   └── OrderRepository.java
├── service/
│   ├── OrderService.java
│   └── UserService.java
├── controller/
│   ├── OrderController.java
│   └── UserController.java
├── dto/
│   ├── OrderCreateDTO.java
│   └── OrderResponseDTO.java
└── HousekeepingApplication.java

image.gif

1. Maven 依赖(pom.xml 核心部分)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

image.gif

2. 实体类

2.1 用户实体(User.java)

package com.housekeeping.entity;
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String phone;
    private String address;
    private LocalDateTime createTime;
}

image.gif

2.2 家政人员实体(Staff.java)

package com.housekeeping.entity;
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "staff")
public class Staff {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String phone;
    private String skill;        // 擅长服务类型
    private Double rating;       // 平均评分
    private Boolean available;   // 是否可接单
    private LocalDateTime createTime;
}

image.gif

2.3 服务项目实体(ServiceItem.java)

package com.housekeeping.entity;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
@Table(name = "service_item")
public class ServiceItem {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;         // 如:日常保洁、深度保洁
    private String description;
    private Double pricePerHour; // 每小时价格
}

image.gif

2.4 订单状态枚举(OrderStatus.java)

package com.housekeeping.entity;
public enum OrderStatus {
    PENDING,      // 待确认
    CONFIRMED,    // 已确认
    PROCESSING,   // 服务中
    COMPLETED,    // 已完成
    CANCELLED     // 已取消
}

image.gif

2.5 订单实体(Order.java)

package com.housekeeping.entity;
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private Long userId;
    @Column(nullable = false)
    private Long staffId;
    @Column(nullable = false)
    private Long serviceItemId;
    private LocalDateTime serviceStartTime;
    private Integer durationHours;     // 服务时长(小时)
    private Double totalPrice;
    private String address;
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    private String comment;            // 评价内容
    private Integer rating;            // 评分1-5
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

image.gif

3. Repository 层

package com.housekeeping.repository;
import com.housekeeping.entity.Order;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.time.LocalDateTime;
import java.util.List;
public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByUserId(Long userId);
    List<Order> findByStaffId(Long staffId);
    // 查询某家政人员在指定时间段是否有重叠订单
    @Query("SELECT COUNT(o) FROM Order o WHERE o.staffId = :staffId " +
           "AND o.status != 'CANCELLED' " +
           "AND o.serviceStartTime < :endTime " +
           "AND (o.serviceStartTime + (o.durationHours || ' hour') ) > :startTime")
    int countOverlappingOrders(@Param("staffId") Long staffId,
                               @Param("startTime") LocalDateTime startTime,
                               @Param("endTime") LocalDateTime endTime);
}

image.gif

注意:上述 JPA 时间运算依赖数据库方言,实际开发中更推荐使用原生查询或改用 Java 逻辑。此处为演示冲突检测思路。

4. DTO 类

package com.housekeeping.dto;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class OrderCreateDTO {
    private Long userId;
    private Long staffId;
    private Long serviceItemId;
    private LocalDateTime serviceStartTime;
    private Integer durationHours;
    private String address;
}

image.gif

package com.housekeeping.dto;
import lombok.Data;
import com.housekeeping.entity.OrderStatus;
import java.time.LocalDateTime;
@Data
public class OrderResponseDTO {
    private Long id;
    private Long userId;
    private Long staffId;
    private Long serviceItemId;
    private LocalDateTime serviceStartTime;
    private Integer durationHours;
    private Double totalPrice;
    private String address;
    private OrderStatus status;
    private LocalDateTime createTime;
}

image.gif

5. 服务层

5.1 订单服务(OrderService.java)

package com.housekeeping.service;
import com.housekeeping.dto.OrderCreateDTO;
import com.housekeeping.dto.OrderResponseDTO;
import com.housekeeping.entity.*;
import com.housekeeping.repository.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
@Service
@RequiredArgsConstructor
public class OrderService {
    private final OrderRepository orderRepository;
    private final UserRepository userRepository;
    private final StaffRepository staffRepository;
    private final ServiceItemRepository serviceItemRepository;
    @Transactional
    public OrderResponseDTO createOrder(OrderCreateDTO dto) {
        // 校验用户、家政人员、服务项目是否存在
        User user = userRepository.findById(dto.getUserId())
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        Staff staff = staffRepository.findById(dto.getStaffId())
                .orElseThrow(() -> new RuntimeException("家政人员不存在"));
        ServiceItem item = serviceItemRepository.findById(dto.getServiceItemId())
                .orElseThrow(() -> new RuntimeException("服务项目不存在"));
        if (!staff.getAvailable()) {
            throw new RuntimeException("该家政人员当前不可接单");
        }
        // 时间冲突检测(简化:通过Java检查重叠)
        LocalDateTime start = dto.getServiceStartTime();
        LocalDateTime end = start.plusHours(dto.getDurationHours());
        boolean conflict = orderRepository.findAll().stream()
                .filter(o -> o.getStaffId().equals(staff.getId()))
                .filter(o -> o.getStatus() != OrderStatus.CANCELLED)
                .anyMatch(o -> {
                    LocalDateTime oStart = o.getServiceStartTime();
                    LocalDateTime oEnd = oStart.plusHours(o.getDurationHours());
                    return start.isBefore(oEnd) && end.isAfter(oStart);
                });
        if (conflict) {
            throw new RuntimeException("该时间段已有其他订单,请重新选择时间");
        }
        // 计算总价
        Double totalPrice = item.getPricePerHour() * dto.getDurationHours();
        Order order = new Order();
        order.setUserId(user.getId());
        order.setStaffId(staff.getId());
        order.setServiceItemId(item.getId());
        order.setServiceStartTime(start);
        order.setDurationHours(dto.getDurationHours());
        order.setTotalPrice(totalPrice);
        order.setAddress(dto.getAddress());
        order.setStatus(OrderStatus.PENDING);
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());
        Order saved = orderRepository.save(order);
        return convertToDTO(saved);
    }
    @Transactional
    public void cancelOrder(Long orderId, Long userId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在"));
        if (!order.getUserId().equals(userId)) {
            throw new RuntimeException("无权操作此订单");
        }
        if (order.getStatus() != OrderStatus.PENDING) {
            throw new RuntimeException("只有待确认的订单才能取消");
        }
        order.setStatus(OrderStatus.CANCELLED);
        order.setUpdateTime(LocalDateTime.now());
        orderRepository.save(order);
    }
    @Transactional
    public void completeOrder(Long orderId, Long staffId, String comment, Integer rating) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在"));
        if (!order.getStaffId().equals(staffId)) {
            throw new RuntimeException("无权操作此订单");
        }
        if (order.getStatus() != OrderStatus.PROCESSING) {
            throw new RuntimeException("只有服务中的订单才能完成");
        }
        order.setStatus(OrderStatus.COMPLETED);
        order.setComment(comment);
        order.setRating(rating);
        order.setUpdateTime(LocalDateTime.now());
        orderRepository.save(order);
    }
    private OrderResponseDTO convertToDTO(Order order) {
        OrderResponseDTO dto = new OrderResponseDTO();
        dto.setId(order.getId());
        dto.setUserId(order.getUserId());
        dto.setStaffId(order.getStaffId());
        dto.setServiceItemId(order.getServiceItemId());
        dto.setServiceStartTime(order.getServiceStartTime());
        dto.setDurationHours(order.getDurationHours());
        dto.setTotalPrice(order.getTotalPrice());
        dto.setAddress(order.getAddress());
        dto.setStatus(order.getStatus());
        dto.setCreateTime(order.getCreateTime());
        return dto;
    }
}

image.gif

6. 控制器层

6.1 订单控制器(OrderController.java)

package com.housekeeping.controller;
import com.housekeeping.dto.OrderCreateDTO;
import com.housekeeping.dto.OrderResponseDTO;
import com.housekeeping.service.OrderService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/orders")
@RequiredArgsConstructor
public class OrderController {
    private final OrderService orderService;
    @PostMapping("/create")
    public ResponseEntity<?> createOrder(@RequestBody OrderCreateDTO dto) {
        try {
            OrderResponseDTO order = orderService.createOrder(dto);
            return ResponseEntity.ok(order);
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
    @PutMapping("/cancel/{orderId}")
    public ResponseEntity<?> cancelOrder(@PathVariable Long orderId, @RequestParam Long userId) {
        try {
            orderService.cancelOrder(orderId, userId);
            return ResponseEntity.ok("订单已取消");
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
    @PutMapping("/complete/{orderId}")
    public ResponseEntity<?> completeOrder(@PathVariable Long orderId,
                                           @RequestParam Long staffId,
                                           @RequestParam String comment,
                                           @RequestParam Integer rating) {
        try {
            orderService.completeOrder(orderId, staffId, comment, rating);
            return ResponseEntity.ok("订单已完成并评价");
        } catch (Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}

image.gif

6.2 用户控制器示例(UserController.java)

package com.housekeeping.controller;
import com.housekeeping.entity.Order;
import com.housekeeping.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
    private final OrderRepository orderRepository;
    @GetMapping("/{userId}/orders")
    public List<Order> getUserOrders(@PathVariable Long userId) {
        return orderRepository.findByUserId(userId);
    }
}

image.gif

7. 配置文件(application.properties)

spring.datasource.url=jdbc:mysql://localhost:3306/housekeeping?useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

image.gif

8. 主启动类

package com.housekeeping;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HousekeepingApplication {
    public static void main(String[] args) {
        SpringApplication.run(HousekeepingApplication.class, args);
    }
}

image.gif

9. 初始化测试数据(可选 CommandLineRunner)

@Component
@RequiredArgsConstructor
public class DataInitializer implements CommandLineRunner {
    private final UserRepository userRepository;
    private final StaffRepository staffRepository;
    private final ServiceItemRepository serviceItemRepository;
    @Override
    public void run(String... args) throws Exception {
        if (userRepository.count() == 0) {
            User user = new User();
            user.setName("张三");
            user.setPhone("13800000000");
            user.setAddress("北京市朝阳区xxx");
            user.setCreateTime(LocalDateTime.now());
            userRepository.save(user);
            Staff staff = new Staff();
            staff.setName("李阿姨");
            staff.setPhone("13911111111");
            staff.setSkill("日常保洁、深度保洁");
            staff.setRating(4.9);
            staff.setAvailable(true);
            staff.setCreateTime(LocalDateTime.now());
            staffRepository.save(staff);
            ServiceItem item = new ServiceItem();
            item.setName("日常保洁");
            item.setDescription("全屋基础清洁");
            item.setPricePerHour(50.0);
            serviceItemRepository.save(item);
        }
    }
}

image.gif

核心业务说明

  1. 下单流程:用户选择服务项目、家政人员、上门时间 → 系统校验人员可用性及时间冲突 → 自动计费 → 生成待确认订单。
  2. 时间冲突检测:通过遍历该人员的未取消订单,判断时间区间是否有重叠。
  3. 订单状态流转:PENDING(待确认)→ CONFIRMED(员工确认后)→ PROCESSING(开始服务)→ COMPLETED(完成+评价),或直接 CANCELLED。
  4. 评价体系:订单完成后可填写文字评价和1-5星评分,后续用于展示家政人员平均分。

此示例可直接扩展为完整项目,加入登录认证(JWT/Spring Security)、支付集成服务人员自动分配位置距离排序等高级功能。

相关文章
|
12天前
|
人工智能 供应链 安全
2026 年全球网络安全威胁态势与关键技术防御研究
本文基于Security Affairs 2026年第576期情报,系统分析Linux无文件远控(QLNX)、Dirty Frag内核提权、AI供应链投毒、Bluekit工业化钓鱼及关键基础设施混合攻击等新型威胁,揭示其内存化、智能化、武器化趋势;提出漏洞治理、供应链管控、钓鱼防御、终端加固、应急响应“五位一体”纵深防御框架,并提供可复现代码与工程化方案。(239字)
233 6
|
11天前
|
存储 弹性计算 运维
阿里云服务器怎么买?四种主要方式详解+注意事项,新手购买参考教程
本文介绍了阿里云服务器的四大购买方式的适用场景与注意事项:自定义购买支持全参数精细配置,适合有技术基础的企业用户;快速购买通过预设模板简化流程,助力新手快速上云;活动购买提供低至38元/年的限时优惠,覆盖99计划、学生300元抵扣金、百炼先用后返等多重权益;云市场镜像购买提供预装环境的开箱即用方案,适合中小企业快速建站。
|
11天前
|
人工智能 API Go
Token 到底是什么?搞懂这个“AI 最小货币单位”,省钱又省心
纯干货,用“乐高积木”比喻,3分钟讲透AI核心概念——Token:它是什么、怎么拆、为何影响输入长度、API费用和AI记忆力。附4个实测省钱技巧,助你省30%以上成本,轻松处理长文本。
|
11天前
|
人工智能 弹性计算 运维
我在阿里云 PAI 上私有化部署了 Qwen3-Coder,推理成本比公有 API 降低了 60%
本文分享Qwen3-Coder私有化部署实战:直击代码隐私、定制需求与长期成本三大痛点;选用PAI-EAS+vLLM方案,30分钟快速部署,AWQ量化降低显存40%;实测较公有API节省60%成本,兼顾安全、性能与性价比。(239字)
|
1月前
|
运维 安全 Windows
Wireshark-4.4.2-x64安装步骤详解(附网络抓包与分析入门教程)
Wireshark-4.4.2-x64.exe 是 Windows 64位版网络抓包分析工具,适用于运维、开发与安全人员。支持实时捕获、协议解析与过滤分析,需以管理员身份安装并启用Npcap驱动,兼容Win10/Win11。(239字)
|
11天前
|
人工智能 弹性计算 API
Hermes Agent + Claude Code 协同编程开发:阿里云一键部署AI开发团队全教程
在AI驱动开发的新时代,单一智能体已难以覆盖从需求分析、任务拆解、代码编写到经验沉淀的全流程。Hermes Agent与Claude Code的组合,构建了一套类似“技术主管+资深工程师”的高效AI开发团队模式。前者负责统筹规划、记忆进化、任务调度,后者专注高质量编码、调试与实现,两者协同工作,可大幅提升开发效率与工程交付质量。
421 1
|
3月前
|
人工智能 Java 决策智能
用Spring AI Alibaba把MultiAgent实现从5天压到5小时
本文详解Spring AI Alibaba新版本的Multi-agent能力,涵盖React/Planning核心模式、手写框架与成熟框架差异,并通过Plan-Execute实战示例,展示如何基于Graph工作流快速构建可扩展、易维护的智能体系统,助力Java开发者高效落地AI应用。
用Spring AI Alibaba把MultiAgent实现从5天压到5小时
|
11天前
|
人工智能 运维 Rust
从Cursor、Claude Code到DeepSeek-TUI:2026年五大开源AI编程助手硬核实测
本文实测Cursor、Cline、Claude Code、Aider、DeepSeek-TUI五款AI编程工具,在相同环境(M1 Mac/1500行Rust项目)下对比任务耗时、代码质量、中文支持与资源占用。聚焦工程落地:IDE派重体验,终端Agent重流程,新锐TUI重成本与中文适配。不吹不黑,只答“哪个不坑你”。
|
11天前
|
人工智能 Linux API
hermes agent 安装教程:安装优化 + 模型配置 + 工具启用指南
Hermes Agent 是 Nous Research 于 2026 年发布的开源自主进化 AI 智能体框架(MIT 协议,Python 编写)。它通过任务沉淀技能、持久化记忆、原生多工具集成与并行子智能体,实现“越用越强”。支持 Linux/macOS/WSL2,安装便捷,面向个人与企业的新一代私有化 AI 助手。
|
5月前
|
算法 开发工具 git
Git基础
本文介绍了Git的四大工作区域:工作区、暂存区、版本库和远程仓库,详解文件在各区域间的流转过程及四种状态(未跟踪、未修改、已修改、已暂存)。涵盖常用命令如init、add、commit、push、pull等,帮助理解Git版本控制的核心流程与操作要点。
340 15

热门文章

最新文章