我有一个包含六个属性和一个更改日期的类。
@Entity
@Table(name = "product")
public class Product {
private Long id;
private String title; // if changed, update lastChanged
private String subtitle;
private Text summary; // if changed, update lastChanged
private Text description; // if changed, update lastChanged
private Text otherText;
private List<Text> reviews; // if changed, update lastChanged
private Date lastChanged;
// Getters and setters
}
-
@Entity
@Table(name = "text")
public class Text {
private Long id;
private String content;
private int typeCode;
// Getters and setters
}
(这显然是我们实际领域模型的大规模简化版本,但它说明了基本问题)
要求是:如果“标题”、“摘要”、“描述”或“评论”发生更改,请将“lastChanged”设置为当前日期。
背景:这些字段与外部 API 相关。我的客户想知道自日期 X 以来哪些产品的 API 相关字段发生了更改。
我尝试通过实现 Hibernate 拦截器和 Hibernate 事件监听器来满足要求。他们都没有像我希望的那样工作。例如,当我更改“摘要”时,Hibernate 只是告诉我:“文本”表中的“内容”字段已更改。
此信息不是很有用,因为我仍然不知道“summary”、“description”或“otherText”是否已更改。因此我不知道是否需要更新“lastChanged”。
我的其他想法:
获取已更改的 Text 对象的 ID,并尝试通过 SQL 查找与其连接的产品。这可能会起作用,但这是一个相当丑陋的解决方案,而且我们的领域模型会变得非常复杂。
在变量 setter 中实现更新逻辑。这样做有两个问题:Hibernate 在从数据库加载对象时调用 setter(这当然不会导致更新时间戳),并且它不能解决上述问题。如果“内容”的设置者被调用,那么怎么办?我不知道,产品的哪些属性被改变了。
这个问题有什么优雅的解决方案吗?
最佳答案
以通用方式解决更改通知问题并非易事,特别是如果您需要一个不会盲目发送通知的有状态机制 - 例如源自基础设施某些部分的更改不会触发通知。
您的问题的具体情况也可能使问题变得简单或复杂。例如可以同样Text
对象被 Product
的多个字段引用目的?同样,它是否可以在不同的Product
之间共享?物体?如果其中任何一个是可能的,那么您必须决定当共享对象更改时正确的操作过程是什么 - 例如您是否通知所有相关方?
构建通知基础设施的基本设计模式之一是 Observer pattern 。您可以使用此方法来获取所有 Product
对象观察所有Text
的变化他们引用的对象。
如果这种方法对于您的目的来说太复杂或太慢,您可能需要重新考虑您的架构。例如,将 Text
设置为有意义吗?类不可变?或者,如果每个 Text
对象仅被单个其他对象引用,是否可以在 Text
中添加额外的字段指向其父对象以及合适的构造函数?
为了避免虚假通知,有一些潜在的解决方案:
限制对 setter 的访问,以保留它们供任何持久性/序列化机制使用,并为系统的其余部分使用一组不同的方法。例如。你可以这样做:
公共(public)课文本{ 长私有(private) ID; ... 私有(private) setPrivateId(长x) { 私有(private)ID = x; }
public setId(long x) { setPrivateId(x); this.triggerChangeNotifiers(); } ...
}
让 Hibernate 直接填写字段,而不需要通过 setter - 我相信有很多注释,但请记住,这种方法可能会使 future 的重构变得更加困难。
里>
关于java - 对变量的设置使用react,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13396354/