Tarek - See inline.
On 09/01/2016 10:11 AM, Dev Stack wrote: > Hi Chris, > > Thank you for your answer. > > 1) yes, we can use Set<> > 2) When we load an offer we have to load also the associated product. > So, we have to keep the link from offer to product. > the link from product to offer is not needed for now. What I meant here was more along the lines of keeping the bidirectional relation, but instead of the @ManyToOne being the owner of the mapping, we'd invert it so that the @OneToMany owned the relationship. The mapping would then be: @Entity @Audited public class Product { ... @OneToMany @JoinColumn(name = "product_offer") @AuditMappedBy(mappedBy = "product") private Set<Offer> offers; ... } @Entity @Audited public class Offer { ... @ManyToOne @JoinColumn(name = "product_offer", insertable = false, updatable = false) private Product product; ... } We want to do this to take advantage of Envers' REVISION_ON_COLLECTION_CHANGE. See below in your point 2 as to why. > Thanks, > Tarek > > 2016-09-01 15:55 GMT+02:00 Chris Cranford <cranc...@gmail.com > <mailto:cranc...@gmail.com>>: > > Tarek - > > There are a few ways we can tackle what you want all within the > scope of Envers, > but some of it highly depends upon details specific to the > relationship between > Product (P) and Offer (O). > > 1. What is the collection type used in Product for the related offers? > If this happens to be a List<>, would it be possible to use a > Set<> instead? > > 2. Is there a requirement that Offer should own the relationship > with Product? > In other words, is it possible to invert the relationship such > that the > collection side is the owner instead? > > Chris > > > On 09/01/2016 06:14 AM, Dev Stack wrote: > > Hello, > > we have in our model entity P (product) and entity O (offer). > The two > entities have a link. > one instance of P can have one or many O instances. > an instance O has a reference to only one instance of P. > The link is managed in the O side. > > P and O are revisioned by Hibernate Envers. > > Two use cases to cover: > 1) If P instance is updated (new revision) we want that O keep > the link > with the old revision of P. > You get this by default. Regardless of which side owns the relationship, any change made specifically to a Product that does not change the associated Offer instances, only a revision is triggered for Product, allowing Offer instances to point to the older versions of a Product when they're queried. If we assume a Product and Offer were created in revision 1 and subsequently the Product was modified in revision 2, the following are true: auditReader.getRevisions( Offer.class, offerId ) = [1] auditReader.getRevisions( Product.class, productId) = [1, 2] So querying Offer at revision 1 would give you the product instance at revision 1 Offer offer = auditReader.find( Offer.class, offerId, 1 ); offer.getProduct() = Product at revision 1 > 2) When I update O instance, I will move the reference to the > last revision > of O instance. > > What we did is, inside O class we added to attributes P.id and > P.revision. > So when we load the object P we use these to fields to load > manually (O DAO > has reference P DAO). > I think it makes more sense to enforce this through Envers than polluting the domain model, but that's just my opinion ;). The cleanest way is to invert the relationship as I described above and change the collection type to a Set<>. The setting REVISION_ON_COLLECTION_CHANGE will take affect since Product now owns the relationship and any change you make to an Offer, the owning entity (Product) will be revised automatically. In other words, changes to an Offer will force Product to update and so the revision number query logic from 1) holds true and helps us here too. NOTE: Just be sure you implement the appropriate equals/hashCode logic for Offer so that changes are properly detected. If you decide you don't want to use REVISION_ON_COLLECTION_CHANGE and invert the relationship between Product and Offer, the only other partial Envers' solution I see might be to introduce some attribute on Product that is audited that your business tier couldchange when an offer is modified, causing the Product to be audited like the following: entityManager.getTransaction().begin(); changedOffer.setCode( "NEWCODE" ); changedOffer.getProduct().pulse(); // updates a field to trigger revision entityManager.merge( changedOffer ); entityManager.getTransaction().commit(); Hope this helps. Chris _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev