I am hoping to get some insight on implementing a graph of resources with multiple many-to-manys.
For my requirements, each resource can have a number of resources that require it (downstream) and are required by it (upstream).
For example: Let's say that A is a web server and B is a database. Adding B as an upstream resource to A, should inversely add A as a downstream resource to B.
The following definition works fine, except for inversely adding A as a downstream resource to B...
Code:
@Entity
@Table(name="omni_resources")
public class Resource {
@Id
@Column(name="resource_id")
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Column(name="name", length=255, nullable=false, unique=true)
private String name;
@Column(name="description", length=8196)
private String description;
@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name="omni_resource_graph",
joinColumns=@JoinColumn(name="downstream_id"),
inverseJoinColumns=@JoinColumn(name="upstream_id"))
private Set<Resource> upstreamResources;
@ManyToMany(cascade={CascadeType.ALL})
@JoinTable(name="omni_resource_graph",
joinColumns=@JoinColumn(name="upstream_id"),
inverseJoinColumns=@JoinColumn(name="downstream_id"))
private Set<Resource> downstreamResources;
...
}
For my test:
Code:
// Create a sample database resource...
Resource myDatabase = new Resource();
myDatabase.setName("mydb");
myDatabase.setDescription("My Database");
log.debug("Saving application...");
myDatabase = resourceDao.save(myDatabase);
// Create a sample application resource...
Resource myApplication = new Resource();
myApplication.setName("myapp");
myApplication.setDescription("My Application");
log.debug("Saving database...");
myApplication = resourceDao.save(myApplication);
// Specify the database as an upstream ersource for the application...
myApplication.addUpstreamResource(myDatabase);
log.debug(String.format("Resaving application (%s)...", myApplication));
myApplication = resourceDao.save(myApplication);
log.debug(String.format("Saved application (%s)...", myApplication));
// Re-retrieve the database...
myDatabase = resourceDao.get(myDatabase.getId());
log.debug(String.format("Retrieved database (%s)...", myDatabase));
// Make sure that the relationships we want are there...
Assert.assertNotNull(myApplication);
Assert.assertNotNull(myDatabase);
Assert.assertNotNull(myApplication.getUpstreamResources());
Assert.assertNotNull(myDatabase.getDownstreamResources());
Assert.assertEquals("Application should have contained one upstream resource (the database).", 1, myApplication.getUpstreamResources().size());
Assert.assertEquals(myDatabase, myApplication.getUpstreamResources().iterator().next());
// TEST FAILS ON THE FOLLOWING LINE...
Assert.assertEquals("Database should have contained one downstream resource (the application).", 1, myDatabase.getDownstreamResources().size());
Assert.assertEquals(myApplication, myDatabase.getDownstreamResources().iterator().next());
When re-retrieving a fresh copy of the database object, it (in my head) should have a reference to the application object.
The upstream and downstream many-to-manys look right in my head, but don't seem to have the intended effect. Could someone make any recommendations based on their experience? Please let me know if I need to clarify this more.
Thanks, I appreciate your time.
Mike