Envers returns all revisions of entity <= reqested revision number in ManyToMany relation
boban_jboss Mar 30, 2011 11:43 AMHi,
it's difficult to explain and my english is soooo bad ...
I have 2(3) entities, one of them are joined over inheritance. The entities FileResource and StorageNode are joined over a ManyToMany relation. Revisioning and other hibernate things are working well, only thing is not working like expected is get StorageNodes of FileResource with specified revision. Envers always return all StorageNodes.REV <= requested revision number? Should it not return only StorageNodes with requested REV? .
I'm using hibernate 3.6.2 and FileResource has 3 revisions
To load a FileResource with id 2 and revison 4 i do:
Resource resource = AuditReaderFactory.get(sessionFactory.getCurrentSession()).find(ResourceImpl.class, 2, 4);
it works like expected, i get the resource with specified revision. To get StorgeNodes of this loaded FileResouce revision i do:
List<StorageNode> storageNodes = resource.getStorageNodes();
This call returns this StorageNodes:
sn_test_name (rev 1) sn2_test_name (rev 3) sn3_test_name (rev 4)
The loaded FileResource 2 with revision 4 is only referenced by sn3_test_name (rev 4) StorageNode. Why envers returns here all revisions? Is it maybe a bug?
Here is an Example of my code and database entries:
@Audited @Entity(name = "resource") @Inheritance(strategy = InheritanceType.JOINED) @SequenceGenerator( name = "resourceIdSequence", sequenceName = "resource_id_seq", allocationSize = 1 ) public class ResourceImpl implements Resource { private static final long serialVersionUID = -5852061235776305002L; @Id @GeneratedValue(generator = "resourceIdSequence", strategy = GenerationType.SEQUENCE) @Column(nullable = false) protected long id; @Column(nullable = false) protected String uuid = UuidGenerator.createUuid(); @NotAudited protected String name; @Temporal(TemporalType.TIMESTAMP) protected Date time; protected String author; @NotAudited protected String path; @NotAudited @ManyToOne(targetEntity = ResourceImpl.class, fetch = FetchType.EAGER) @JoinColumn(name = "parent_id") protected Resource parent; @NotAudited @OneToMany(targetEntity = ResourceImpl.class, mappedBy = "parent", fetch = FetchType.LAZY, orphanRemoval = true) protected List<Resource> children; @NotAudited @ManyToOne(targetEntity = NamespaceImpl.class, fetch = FetchType.EAGER) @JoinColumn(name = "namespace_id") protected Namespace namespace; @NotAudited @OneToOne(targetEntity = LockInfoImpl.class, mappedBy = "resource", orphanRemoval = true) protected LockInfo lockInfo; @NotAudited @OneToMany(targetEntity = ResourcePropertyImpl.class, mappedBy = "resource", fetch = FetchType.LAZY, orphanRemoval = true) protected List<ResourceProperty> properties; ... getter setter }
@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED) @Entity(name = "fileresource") @Table(name = "file_resource") @PrimaryKeyJoinColumn(name = "resource_id") public class FileResourceImplextends ResourceImpl implements FileResource { private static final long serialVersionUID = -3576586818372426631L; private long size; private String hash; @NotAudited private boolean expired = false; @ManyToMany(targetEntity = StorageNodeImpl.class, fetch = FetchType.LAZY) @JoinTable(name = "stored_resource", joinColumns = @JoinColumn(name = "resource_id"), inverseJoinColumns = @JoinColumn(name = "storagenode_name") ) private List<StorageNode> storageNodes; ... getter setter }
@Entity(name = "storagenode") @Table(name = "storage_node") public class StorageNodeImpl implements StorageNode{ private static final long serialVersionUID = 2321859209769972438L; @Id @Column(nullable = false) private String name; private int port = 80; @Enumerated(EnumType.STRING) private StorageNode.Status status; @Column(nullable=false) private long capacity; @Column(name = "free_capacity", nullable = false) private long freeCapacity = 0; @Temporal(TemporalType.TIMESTAMP) @Column(name = "last_capacity_check") private Date lastCapacityCheck; @Column(name = "mount_point", length = 512, nullable = false) private String mountPoint = "/opt/archive"; @ManyToMany(targetEntity = FileResourceImpl.class, mappedBy = "storageNodes", fetch = FetchType.LAZY) private List<FileResource> fileResources; @NotAudited @OneToMany(targetEntity = ReservationImpl.class, mappedBy = "storageNode", fetch = FetchType.LAZY) private List<Reservation> reservations; ... getter setter }
Table revison_entity:
id | author | timestamp | expired ----+--------+---------------+--------- 1 | CADN | 1301489501186 | f 2 | CADN | 1301490327329 | f 3 | CADN | 1301491018255 | f 4 | CADN | 1301491591750 | f
Table resource_aud:
id | rev | revtype | author | time | uuid ----+-----+---------+--------+---------------------+---------------------------------- 1 | 1 | 0 | Author | 2010-09-01 00:00:00 | 0dc9b45bd4444890a3bb6880988175ef 2 | 1 | 0 | Author | 2010-09-01 00:00:00 | 33701ac5938d46c188b633381436560a 2 | 2 | 1 | Boban | 2010-09-01 00:00:00 | 33701ac5938d46c188b633381436560a 2 | 3 | 1 | Boban | 2010-09-01 00:00:00 | 33701ac5938d46c188b633381436560a 2 | 4 | 1 | Boban | | uiuiuiuiuiuiuiuiuiu
Table file_resource_aud:
resource_id | rev | hash | size -------------+-----+------+------ 2 | 1 | | 0 2 | 2 | | 1111 2 | 3 | | 1111 2 | 4 | | 1111
Table stored_resource_aud (the join table resource <-> storage_node):
rev | resource_id | storagenode_name | revtype -----+-------------+------------------+--------- 1 | 2 | sn_test_name | 0 3 | 2 | sn2_test_name | 0 4 | 2 | sn3_test_name | 0
Table storage_node:
name | port | capacity | status | free_capacity | last_capacity_check | mount_point ---------------+------+------------+--------+---------------+----------------------------+-------------- sn_test_name | 80 | 1073741824 | ACTIVE | 0 | | /opt/archive sn2_test_name | 80 | 10000000 | ACTIVE | 333 | 2011-03-30 15:01:47.18339 | /opt/archive sn3_test_name | 80 | 10000000 | ACTIVE | 444 | 2011-03-30 15:25:51.784414 | /opt/archive