Java 对变量的设置作出反应
我有一个有六个属性和更改日期的类Java 对变量的设置作出反应,java,hibernate,javabeans,Java,Hibernate,Javabeans,我有一个有六个属性和更改日期的类 @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 pri
@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
}
(这显然是我们实际领域模型的一个大规模简化版本,但它说明了基本问题)
要求是:如果“标题”、“摘要”、“说明”或“评论”更改,请将“lastChanged”设置为当前日期。背景:这些字段与外部API相关。我的客户想知道,自日期X以来,哪些产品对API相关字段进行了更改 我已经尝试通过实现Hibernate拦截器和Hibernate事件侦听器来满足需求。他们都没有像我希望的那样工作。例如,当我更改“summary”时,Hibernate只告诉我:表“text”中的字段“content”已更改 这些信息不是很有用,因为我仍然不知道“摘要”、“说明”或“其他文本”是否已更改。因此,我不知道是否需要更新“lastChanged” 我的其他想法:
- 获取已更改文本对象的id,并尝试通过SQL查找与其连接的产品。这可能会起作用,但这是一个相当丑陋的解决方案,而且它会变得非常复杂,与我们的领域模型
- 在变量设置器中实现更新逻辑。这有两个问题:Hibernate在从数据库加载对象时调用setter(当然,这不应该导致更新时间戳),它不能解决上述问题。如果调用了“内容”的setter,那么会发生什么?我不知道,产品的哪个属性已经改变了
这个问题有什么优雅的解决方案吗?以一种通用的方式解决更改通知问题不是一件小事,特别是当您需要一种不会盲目发送通知的有状态机制时——例如,来自基础结构某些部分的更改不会触发通知 问题的细节也可能使问题变得简单或复杂。例如,同一
文本
对象能否被产品
对象的多个字段引用?同样,它是否可以在不同的产品对象之间共享?如果其中任何一项都是可能的,那么当共享对象发生更改时,您必须确定正确的行动方案-例如,您是否通知所有相关方
构建通知基础架构的基本设计模式之一是。您可以使用此方法让所有Product
对象观察它们引用的所有文本
对象中的更改
如果这种方法对于您的目的来说太复杂或太慢,您可能需要重新思考您的体系结构。例如,使Text
类不可变有意义吗?或者,如果每个Text
对象仅由单个其他对象引用,是否可以在Text
中添加一个额外字段,以指向其父对象以及合适的构造函数
至于避免虚假通知,有两种可能的解决方案:
- 限制对setter的访问以保留它们供任何持久性/序列化机制使用,并为系统的其余部分使用不同的方法集。例如,你可以这样做:
公共类文本{
长私形;
...
私有setPrivateId(长x){
privateId=x;
}
}
- 让Hibernate直接填充字段,而不经过setter——我相信有很多注释,但请记住,这种方法可能会使未来的重构更加困难
您想知道实体的变更属性吗?我不太明白这个问题。您想知道,如果我需要更改实际值(旧值是什么,新值是什么)?那很好,但没必要。
@Entity
@Table(name = "text")
public class Text {
private Long id;
private String content;
private int typeCode;
// Getters and setters
}
public setId(long x) {
setPrivateId(x);
this.triggerChangeNotifiers();
}
...