【问题标题】:JPA: Singleton EntityJPA:单例实体
【发布时间】:2016-12-27 11:36:24
【问题描述】:

我有一个案例来处理一个只有一个实例的实体。

案例是建模一个Configuration类,创建一次,更新多次,永不删除。

主要思想是,实体将类似于属性文件,但保留在数据库中。

对这个类建模有什么建议,有什么技巧或想法吗?

【问题讨论】:

  • 这是什么:UML 还是实现问题?
  • 这是一个 JPA 建模问题
  • 有趣的是,仅与实现相关的答案被投票赞成。因此,您要么寻求 UML 解决方案,要么寻求实现解决方案。请澄清!

标签: java hibernate jpa spring-data


【解决方案1】:

我不会将其建模为单个 JPA 实体,而是使用实现以下方法的 Facade

Configuration getConfiguration(String key);
Configuration addConfiguration(Configuration configuration);
Configuration updateConfiguration(Configuration configuration);
void deleteConfiguration(Configuration configuration);
Collection<Configuration> getCompleteConfiguration();

当然,如果需要,您可以随意添加其他方法。此门面使用存储库来执行与持久性相关的任务。根据您的设置、复杂性和架构,您可能希望在存储库中使用的实际配置 JPA 实体和外观使用的配置类之间添加映射。

实际的 ConfigurationEntity 可能如下所示(随意添加额外的 JPA 注释和/或列)

@Entity
@Table(name = "CONFIGURATION")
public class ConfigurationEntity {

    @Id
    @GeneratedValue
    private Long id;
    private String key;
    private String value;
....

【讨论】:

  • 如何将 ConfigurationEntity 连接到 Configuration 类?
  • Facade 使用存储库读取 ConfigurationEnties。然后它为 ConfigurationEntities 创建配置对象并将属性值从实体复制到对象(反之亦然,对于它接收的参数)。这将持久层与应用层分开。您可以使用 orika (orika-mapper.github.io/orika-docs/intro.html) 之类的映射工具进行映射。
【解决方案2】:

我将回答一个更一般的问题 - 如何很好地实现数据库存储应用程序配置

一般来说,您可能会针对应用程序的不同范围进行配置,而不是单一的多合一配置。 IE。例如,您可能有 CarConfig、CacheConfig、BookingConfig 等,包括一些通用的 AppConfig。有时您需要在开发过程中添加/删除属性。

所以为了方便处理,我建议您使用一个 single 字符串键/值配置表来服务所有配置.方法如下:

为每个配置创建一个这样的界面:

public interface CarConfig {       
    @PropertyName("default.color")
    @DefaultValue("red")
    String getDefaultColor();

    void setDefaultColor(String color);

    @PropertyName("max.size")
    @DefaultValue(100)
    int getMaxSize();

    void setMaxSize(int size);

    ...
}

在应用程序启动时,单个配置实现被实例化,然后在应用程序之间共享。实现是通过创建代理来完成的。

对于getters,代理分析调用的方法(例如:getDefaultColor())——它从注解@PropertyName 中获取属性名称。然后,它使用该属性名称查询数据库中的配置表。该值被转换(因为它作为字符串存储在表中)为方法返回类型(在 getMaxSize() 为 int 的情况下)并返回。

对于 setters,代理将给定值保存到配置表中。无需复制 @PropertyName - 它可以从相应的 getter 派生。

所以当你需要一个配置属性值时,你可以这样:

CarConfig carConfig = configs.get(CarConfig.class);
String defaultColor = carConfig.getDefaultColor();

为什么配置实现应该是单例并在应用程序之间共享?因为在这种情况下您可以启用缓存 - 如果您确保配置属性始终仅通过您的配置使用,您可以在启动时读取所有值并将它们存储在内存中,然后根本不查询数据库,因为没有除了您的配置类之外的任何其他更改来源。 Setter 会更新缓存的值以及数据库配置表。

配置表类似于:

|     key       |value |
...
|"default.color"|"blue"|
|"max.size"     |"85"  |
...

因此,在单个配置表的情况下,添加新属性只需将 getter 和 setter 添加到类 - 代理会自动获取它。

在 CUBA 开源框架中使用了类似的架构 - https://www.cuba-platform.com/

相反,为单独的配置提供一个单独的表具有以下特点:

  • 您需要为每个配置创建一个新表;
  • 添加/删除新配置属性需要更改表架构。

【讨论】:

  • @PropertyName("max.size") @DefaultValue(100) 是什么?你用的是什么框架?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-14
  • 2020-12-22
  • 1970-01-01
  • 2011-01-28
  • 2022-09-27
相关资源
最近更新 更多