gpt4 book ai didi

java - Spring JPA,更新实体属性时的附加数据库操作

转载 作者:行者123 更新时间:2023-12-02 02:24:15 25 4
gpt4 key购买 nike

我正在使用 Spring JPA 设计一个电子商务 Web 应用程序。我有 2 个类 ProductCategory,其中 Product 可以分配给许多类别,但 Category 可以不关心产品

@Entity(name = "products")
class Product {
@Id
@Column(name = "product_id")
private Long productId;

@ManyToMany
@JoinTable(
name = "product_category_links",
joinColumns = @JoinColumn(name = "product_id", referencedColumnName = "product_id"),
inverseJoinColumns = @JoinColumn(name = "category_id", referencedColumnName = "category_id"))
private List<Category> categories;

// getters, setters,
}

@Entity(name = "categories")
class Category {
@Id
@Column(name = "category_id")
private Long category_id;

// getters, setters
}

产品的类别发生更改时,我还需要更新数据库中的某些内容。我正在考虑通过创建专门的服务方法来更新产品类别来保持这种完整性。

class ProductService
@Autowired
private ProductRepository productRepository;
private ComplexDBService complexDBService;

@Transactional
public void addCategory(Long productId, Long categoryId) {
Product p = productRepository.findByProductId(productId);
Category c = categoryRepository.findByCategoryId(categoryId);
p.getCategories.add(c);
complexDBService.doSomething();
}
}

但我认为这不切实际,因为 Product 仍然可以在其他地方更改类别。例如,在 Controller 中,某人可以直接从存储库获取Product并可以更改其类别。我不想禁止这个用例。

所以我正在考虑将逻辑 addCategory(Long ProductId, Long CategoryId) 放在 Product 类本身中,这实际上是由领域驱动设计建议的。但我不知道如何做到这一点,因为我无法将 ComplextDBService 注入(inject) Product 中。一种方法是将其作为参数传递给 addCategory 方法,如 addCategory(Long ProductId, Long CategoryId, ComplextDBService complexDBService),这是一个好的做法吗? 是否有其他方法可以将自定义数据库操作逻辑放入域类中?

最佳答案

addCategory(Long productId, Long categoryId, ComplextDBService complexDBService), is this a good practice?

不,不是。在复杂的业务案例中,您有时必须将某种“服务”作为参数传递到聚合调用的方法中,但根据经验,您应该只在此“服务”上调用只读查询方法。

Is there some other ways to put custom database manipulation logic in a domain class?

产品聚合中应该只出现与产品相关的内容,例如操纵产品状态。您的要求是响应产品聚合中发生的事件。

领域事件来救援

您需要反转控件。产品聚合应该向外部通报其内部的事件,并且外部应该对此使用react。产品不应依赖于其他不相关的聚合/概念。

class Product {
void addCategory(CategorySnapshot category) {
categories.add(category);
eventPublisher.publish(new ProductCategoryAdded(getSnapshot(), category));
}
}

现在你应该注册其他组件来监听 ProductCategoryAdded 事件,其他组件是什么并不重要(如果你需要进行数据库操作,也许你正在实现 CQRS?)。

您可以自己实现发布者或使用 Guava Event Bus、Axon 等框架。

顺便说一句,您错过了 DDD 的许多重要概念。

  1. 聚合产品不应该包含其他聚合类别的列表(也许您的项目的这个有界上下文根本不应该使用 DDD 来实现?)
  2. 您不应将对象直接添加到聚合所拥有的列表中 p.getCategories.add(c)
  3. //getters、setters - 这些不是面向对象的......

关于java - Spring JPA,更新实体属性时的附加数据库操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48021711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com