Java 在Hibernate环境中,如何使实体的早期修订成为最新修订
我的应用程序使用HibernateEnvers4.3.11 我将音乐文件及其元数据加载到我的数据库中,例如专辑标题、艺术家表示为已审核的歌曲类 然后,应用程序以各种方式编辑元数据,并在每次提交会话创建另一个修订时回写到Song类 然后通常在最后,更改会从当前的Song类写回文件本身。 但如果在预览模式下运行,则不会向文件写入任何内容。因此,我希望该文件的Song类的最新版本现在包含与最初加载该文件时创建的版本相同的元数据。 目前,我通过获取歌曲的第一个版本并将其保存的数据复制到歌曲的最新版本来实现这一点。但是有没有一种方法可以让我说,把这个早期的版本变成最新的版本 更新 我现在正在实现Naros的答案。现在我有一个名为SongFile的类,它总是表示磁盘上音乐文件的内容,这是@Audited by Envers,主id是@GeneratedValue 然后我们有一个名为Song的类,在创建并省略SongFile实体后,我们创建了一个等效的Song实体。这是未审核的,主id是手动设置的,我们将主id和所有元数据设置为与Song类相同 然后,应用程序将元数据修改为歌曲 最后,若在预览模式下,我们只需比较Song和SongFile之间的差异并生成报告 若在实际保存模式下,我们比较Song和SongFile之间的差异,生成报告并将更改保存回文件和SongFile 这非常有效,解决了许多问题 但是我有一个问题,音乐文件也可以存储多个图像JPEG等,我们使用CoverImage类表示图像,CoverArt类提供歌曲和CoverImage之间的1:M链接,还存储名称属性 现在的问题是,我创建了一个由SongFile使用的、使用@GeneratedValue的covertartfile类和一个由Song使用的、不自动生成的covertart类 当最初加载一个文件并创建SongFile和Song时,将自动生成的值从任何covertartfile类复制到covertart类就可以了 但是,如果我们没有coverart开始,然后它被应用程序添加,我们会失败,因为coverart类不会自动生成主键,并且我无法安全地生成主键,以防它被现有的covertartfile类使用或将来会被使用 或者,如果我让covertar使用一个自生值,那么它将不会与其关联的covertartfile类使用的值相同Java 在Hibernate环境中,如何使实体的早期修订成为最新修订,java,hibernate,hibernate-envers,Java,Hibernate,Hibernate Envers,我的应用程序使用HibernateEnvers4.3.11 我将音乐文件及其元数据加载到我的数据库中,例如专辑标题、艺术家表示为已审核的歌曲类 然后,应用程序以各种方式编辑元数据,并在每次提交会话创建另一个修订时回写到Song类 然后通常在最后,更改会从当前的Song类写回文件本身。 但如果在预览模式下运行,则不会向文件写入任何内容。因此,我希望该文件的Song类的最新版本现在包含与最初加载该文件时创建的版本相同的元数据。 目前,我通过获取歌曲的第一个版本并将其保存的数据复制到歌曲的最新版本来实
如何继续?首先,没有自动方式来完成您的请求。此过程必须完全手动并在应用程序中进行编码,因为存在许多实体细微差别和业务注意事项,最好由应用程序来决定和处理 所以最好的方法是 从要还原到的审核历史记录中获取所需的修订。 从Hibernate获取现有实体。 将现有图元中的值从2设置为从1中获取的所需修订的值。 合并修改后的实体。
另一个可行的想法是考虑预览和非预览的概念。我的意思是你有两个实体而不是一首歌。一个表示高电压版本的预览,另一个表示低电压非预览,表示文件内容
在这种方法中,当您修改预览变量时,您只需使用Envers创建一个更改日志,记录本可以对文件进行更改但不是由于预览模式引起的更改。修改非预览变量时,您正在为文件内容创建更改日志 这里需要注意的是,在这个用例中,您的业务逻辑可能还应该同步预览变量,以便预览和非预览具有相同的内容,因此基本上加载预览实体,修改它以匹配非预览,然后保存对它的更改 如果这两种实体类型都有一个公共主键或自然id,那么管理起来应该足够容易,并允许您生成所有类型的报告,并维护一致的历史记录,而不会混淆问题 使现代化 补充我关于您更新的回答;在这里,您可能希望为所有实体使用生成的标识符,并让您的Song和CoverArt实体维护对已审核实体的引用,或者至少存储主键值 例如@Entity
public class Song {
@Id
@GeneratedValue
private Long id;
@OneToOne
private SongFile songFile;
}
或者更简单地说
@Entity
public class Song {
@Id
@GeneratedValue
private Long id;
private Long songFileId;
}
其思想是,您的非基于文件的实体通过关联(例如@OneToOne)或存储关联实体的标识符来维护与文件端的关系,以便您可以
确定是否需要获取/复制或构造/插入。因此,在预览模式下,即使不需要这些更改,也允许事务提交到数据库中?这些更改可能是需要的,但只写入数据库而不是文件本身,这样我们就可以创建一个报告,显示可能进行的更改如果不是在预览模式下运行,则提交文件。那么@Naros有什么想法吗?好的,谢谢您确认无法自动完成。我理解你的另一个想法,但是预览的起点将是文件的现有内容非u预览,因此在第一次加载文件并创建歌曲后,我必须创建预览并复制数据,然后在最后阶段,如果不是预览模式,我必须再次复制。因此,我不确定这是否比我目前拥有的更好,但我会进一步考虑。嗯,我认为这是一个好主意,但由于song确实与其他一些数据覆盖有1:M的关系,这也需要复制。我正在实施您的解决方案,因为我认为它可以解决许多问题,然而,我有一个问题与CoverArt。我已经通过问题进行了更新,希望您能帮助我。@PaulTaylor请查看我的更新,并让我知道这是否解决了您最近对该方法的担忧。我不需要为歌曲课做这些,但好吧,我已经在想,我将不得不自动生成CoverArt Id,这确实提供了一种跟踪的方法,尽管不像Song类那么简单。