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应用程序。
相关推荐
编程彩机2 小时前
互联网大厂Java面试:从分布式缓存到消息队列的技术场景解析
java·redis·面试·kafka·消息队列·微服务架构·分布式缓存
她说..2 小时前
策略模式+工厂模式实现单接口适配多审核节点
java·spring boot·后端·spring·简单工厂模式·策略模式
csdn_aspnet2 小时前
ASP.NET 8 - Cookie 身份验证
后端·asp.net·cookie·.net8
坚持就完事了2 小时前
Java的OOP
java·开发语言
笔画人生2 小时前
Cursor + 蓝耘API:用自然语言完成全栈项目开发
前端·后端
像少年啦飞驰点、2 小时前
零基础入门 Spring Boot:从“Hello World”到可部署微服务的完整学习路径
java·spring boot·微服务·编程入门·后端开发
undsky_3 小时前
【RuoYi-SpringBoot3-Pro】:将 AI 编程融入传统 java 开发
java·人工智能·spring boot·ai·ai编程
不光头强3 小时前
shiro学习要点
java·学习·spring
工一木子3 小时前
Java 的前世今生:从 Oak 到现代企业级语言
java·开发语言