Hibernate(76)如何在混合持久化环境中使用Hibernate?

在混合持久化环境中使用Hibernate,意味着使用不同的数据库或存储技术来处理不同的数据持久化需求。例如,可以同时使用关系型数据库(如MySQL)和NoSQL数据库(如MongoDB)。这种方法在CQRS(Command Query Responsibility Segregation)或其他多存储技术架构中非常常见。

下面我们将展示如何在Spring Boot项目中结合Hibernate和MongoDB实现混合持久化。

1. 项目依赖

pom.xml中添加必要的依赖:

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MySQL Connector -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.26</version>
    </dependency>

    <!-- HikariCP for Connection Pooling -->
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
        <version>4.0.3</version>
    </dependency>

    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Starter Data MongoDB -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

2. 配置数据源和属性

application.properties中配置MySQL和MongoDB数据源:

properties 复制代码
# MySQL Database Configuration
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=root
spring.datasource.password=rootpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

# MongoDB Configuration
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=myquerydatabase

3. 创建领域模型

使用MySQL的实体类和仓储接口
Order.java
java 复制代码
import lombok.Data;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Data
@Entity
@Table(name = "orders")
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String customerName;
    private String customerAddress;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "order_id")
    private List<OrderItem> items = new ArrayList<>();

    public void addItem(OrderItem item) {
        items.add(item);
    }

    public void removeItem(OrderItem item) {
        items.remove(item);
    }

    // Business logic methods
    public double calculateTotalPrice() {
        return items.stream().mapToDouble(OrderItem::getTotalPrice).sum();
    }
}
OrderItem.java
java 复制代码
import lombok.Data;
import javax.persistence.*;

@Data
@Entity
@Table(name = "order_items")
public class OrderItem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String product;
    private int quantity;
    private double price;

    public double getTotalPrice() {
        return quantity * price;
    }
}
OrderRepository.java
java 复制代码
import org.springframework.data.jpa.repository.JpaRepository;

public interface OrderRepository extends JpaRepository<Order, Long> {
}
使用MongoDB的实体类和仓储接口
OrderView.java
java 复制代码
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Data
@Document(collection = "orders")
public class OrderView {

    @Id
    private String id;
    private String customerName;
    private String customerAddress;
    private double totalPrice;
}
OrderViewRepository.java
java 复制代码
import org.springframework.data.mongodb.repository.MongoRepository;

public interface OrderViewRepository extends MongoRepository<OrderView, String> {
}

4. 创建服务层

写操作服务(Command Service)
OrderCommandService.java
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderCommandService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private OrderViewRepository orderViewRepository;

    @Transactional
    public Order createOrder(Order order) {
        Order savedOrder = orderRepository.save(order);
        syncOrderView(savedOrder);
        return savedOrder;
    }

    @Transactional
    public Order updateOrder(Order order) {
        Order updatedOrder = orderRepository.save(order);
        syncOrderView(updatedOrder);
        return updatedOrder;
    }

    @Transactional
    public void deleteOrder(Long id) {
        orderRepository.deleteById(id);
        orderViewRepository.deleteById(id.toString());
    }

    private void syncOrderView(Order order) {
        OrderView orderView = new OrderView();
        orderView.setId(order.getId().toString());
        orderView.setCustomerName(order.getCustomerName());
        orderView.setCustomerAddress(order.getCustomerAddress());
        orderView.setTotalPrice(order.calculateTotalPrice());
        orderViewRepository.save(orderView);
    }
}
读操作服务(Query Service)
OrderQueryService.java
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class OrderQueryService {

    @Autowired
    private OrderViewRepository orderViewRepository;

    public List<OrderView> getAllOrders() {
        return orderViewRepository.findAll();
    }

    public Optional<OrderView> getOrderById(String id) {
        return orderViewRepository.findById(id);
    }
}

5. 创建控制器

写操作控制器(Command Controller)
OrderCommandController.java
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public class OrderCommandController {

    @Autowired
    private OrderCommandService orderCommandService;

    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
        Order order = new Order();
        order.setCustomerName(request.getCustomerName());
        order.setCustomerAddress(request.getCustomerAddress());
        order.getItems().addAll(request.getItems());
        Order createdOrder = orderCommandService.createOrder(order);
        return ResponseEntity.ok(createdOrder);
    }

    @PutMapping("/{id}")
    public ResponseEntity<Order> updateOrder(@PathVariable Long id, @RequestBody UpdateOrderRequest request) {
        Order order = new Order();
        order.setId(id);
        order.setCustomerName(request.getCustomerName());
        order.setCustomerAddress(request.getCustomerAddress());
        order.getItems().addAll(request.getItems());
        Order updatedOrder = orderCommandService.updateOrder(order);
        return ResponseEntity.ok(updatedOrder);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteOrder(@PathVariable Long id) {
        orderCommandService.deleteOrder(id);
        return ResponseEntity.noContent().build();
    }
}
读操作控制器(Query Controller)
OrderQueryController.java
java 复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/order-views")
public class OrderQueryController {

    @Autowired
    private OrderQueryService orderQueryService;

    @GetMapping
    public ResponseEntity<List<OrderView>> getAllOrders() {
        List<OrderView> orders = orderQueryService.getAllOrders();
        return ResponseEntity.ok(orders);
    }

    @GetMapping("/{id}")
    public ResponseEntity<OrderView> getOrderById(@PathVariable String id) {
        return orderQueryService.getOrderById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}
请求对象
CreateOrderRequest.java
java 复制代码
import lombok.Data;
import java.util.List;

@Data
public class CreateOrderRequest {
    private String customerName;
    private String customerAddress;
    private List<OrderItem> items;
}
UpdateOrderRequest.java
java 复制代码
import lombok.Data;
import java.util.List;

@Data
public class UpdateOrderRequest {
    private String customerName;
    private String customerAddress;
    private List<OrderItem> items;
}

6. 运行应用

  1. 启动MySQL :确保你的MySQL数据库运行在localhost:3306
  2. 创建数据库 :创建一个名为mydatabase的数据库。
  3. 启动MongoDB :确保MongoDB数据库运行在localhost:27017
  4. 启动Spring Boot应用:运行Spring Boot应用程序。
相关推荐
Lee川2 小时前
mini-cursor 揭秘:从 Tool 定义到 Agent 循环的完整实现
前端·人工智能·后端
一直不明飞行3 小时前
Java的equals(),hashCode()应该在什么时候重写
java·开发语言·jvm
REDcker3 小时前
有限状态机与状态模式详解 FSM建模Java状态模式与C++表驱动模板实践
java·c++·状态模式
你的保护色4 小时前
【无标题】
java·服务器·网络
basketball6164 小时前
C++ 构造函数完全指南:从入门到进阶
java·开发语言·c++
淘矿人4 小时前
Claude辅助DevOps实践
java·大数据·运维·人工智能·算法·bug·devops
星浩AI4 小时前
OpenHuman 对比 OpenClaw、Hermes Agent
人工智能·后端·agent
小江的记录本5 小时前
【Java基础】泛型:泛型擦除、通配符、上下界限定(附《思维导图》+《面试高频考点清单》)
java·数据结构·后端·mysql·spring·面试·职场和发展
来恩10035 小时前
请求转发与响应重定向的使用
java
@杰克成5 小时前
Java学习30
java·开发语言·学习